@atlaskit/eslint-plugin-design-system 10.8.2 → 10.10.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 (59) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -0
  3. package/constellation/consistent-css-prop-usage/usage.mdx +9 -0
  4. package/constellation/index/usage.mdx +1 -0
  5. package/constellation/no-custom-icons/usage.mdx +36 -0
  6. package/dist/cjs/presets/all.codegen.js +2 -1
  7. package/dist/cjs/rules/consistent-css-prop-usage/index.js +19 -2
  8. package/dist/cjs/rules/ensure-design-token-usage/index.js +199 -227
  9. package/dist/cjs/rules/index.codegen.js +3 -1
  10. package/dist/cjs/rules/no-custom-icons/checks/has-prop.js +12 -0
  11. package/dist/cjs/rules/no-custom-icons/checks/is-from-import-source.js +42 -0
  12. package/dist/cjs/rules/no-custom-icons/checks/is-imported-jsx-element.js +10 -0
  13. package/dist/cjs/rules/no-custom-icons/index.js +67 -0
  14. package/dist/cjs/rules/no-legacy-icons/index.js +11 -83
  15. package/dist/cjs/rules/use-tokens-typography/index.js +4 -8
  16. package/dist/cjs/rules/utils/error-boundary.js +58 -11
  17. package/dist/es2019/presets/all.codegen.js +2 -1
  18. package/dist/es2019/rules/consistent-css-prop-usage/index.js +19 -2
  19. package/dist/es2019/rules/ensure-design-token-usage/index.js +16 -30
  20. package/dist/es2019/rules/index.codegen.js +3 -1
  21. package/dist/es2019/rules/no-custom-icons/checks/has-prop.js +4 -0
  22. package/dist/es2019/rules/no-custom-icons/checks/is-from-import-source.js +23 -0
  23. package/dist/es2019/rules/no-custom-icons/checks/is-imported-jsx-element.js +4 -0
  24. package/dist/es2019/rules/no-custom-icons/index.js +61 -0
  25. package/dist/es2019/rules/no-legacy-icons/index.js +11 -65
  26. package/dist/es2019/rules/use-tokens-typography/index.js +3 -7
  27. package/dist/es2019/rules/utils/error-boundary.js +55 -11
  28. package/dist/esm/presets/all.codegen.js +2 -1
  29. package/dist/esm/rules/consistent-css-prop-usage/index.js +19 -2
  30. package/dist/esm/rules/ensure-design-token-usage/index.js +199 -227
  31. package/dist/esm/rules/index.codegen.js +3 -1
  32. package/dist/esm/rules/no-custom-icons/checks/has-prop.js +6 -0
  33. package/dist/esm/rules/no-custom-icons/checks/is-from-import-source.js +36 -0
  34. package/dist/esm/rules/no-custom-icons/checks/is-imported-jsx-element.js +4 -0
  35. package/dist/esm/rules/no-custom-icons/index.js +61 -0
  36. package/dist/esm/rules/no-legacy-icons/index.js +11 -83
  37. package/dist/esm/rules/use-tokens-typography/index.js +4 -8
  38. package/dist/esm/rules/utils/error-boundary.js +56 -10
  39. package/dist/types/index.codegen.d.ts +1 -0
  40. package/dist/types/presets/all.codegen.d.ts +2 -1
  41. package/dist/types/rules/consistent-css-prop-usage/types.d.ts +1 -0
  42. package/dist/types/rules/index.codegen.d.ts +1 -0
  43. package/dist/types/rules/no-custom-icons/checks/has-prop.d.ts +2 -0
  44. package/dist/types/rules/no-custom-icons/checks/is-from-import-source.d.ts +8 -0
  45. package/dist/types/rules/no-custom-icons/checks/is-imported-jsx-element.d.ts +8 -0
  46. package/dist/types/rules/no-custom-icons/index.d.ts +3 -0
  47. package/dist/types/rules/no-legacy-icons/index.d.ts +1 -2
  48. package/dist/types/rules/utils/error-boundary.d.ts +8 -5
  49. package/dist/types-ts4.5/index.codegen.d.ts +1 -0
  50. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -1
  51. package/dist/types-ts4.5/rules/consistent-css-prop-usage/types.d.ts +1 -0
  52. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -0
  53. package/dist/types-ts4.5/rules/no-custom-icons/checks/has-prop.d.ts +2 -0
  54. package/dist/types-ts4.5/rules/no-custom-icons/checks/is-from-import-source.d.ts +8 -0
  55. package/dist/types-ts4.5/rules/no-custom-icons/checks/is-imported-jsx-element.d.ts +8 -0
  56. package/dist/types-ts4.5/rules/no-custom-icons/index.d.ts +3 -0
  57. package/dist/types-ts4.5/rules/no-legacy-icons/index.d.ts +1 -2
  58. package/dist/types-ts4.5/rules/utils/error-boundary.d.ts +8 -5
  59. package/package.json +1 -1
@@ -1,3 +1,9 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
3
+ // Need to intersect type RuleListener with a generic function to allow use of Parameters<...> to be used
4
+
5
+ // Allow config to be to be easily passed from rules
6
+
1
7
  /**
2
8
  * ESLint rules should NEVER throw exceptions, because that breaks the VSCode ESLint server
3
9
  * (and probably the IntelliJ one too), which causes linting to fail in a file.
@@ -5,15 +11,53 @@
5
11
  * It also breaks CI, which was the reason this error boundary was added. It's a final
6
12
  * catch all.
7
13
  */
8
- export const errorBoundary = (func, {
9
- config
10
- }) => {
11
- try {
12
- func();
13
- } catch (err) {
14
- if (!config.failSilently) {
15
- // eslint-disable-next-line no-console
16
- console.warn(err);
17
- }
14
+ export function errorBoundary(ruleOrRules, config = false) {
15
+ const failSilently = failSilentlyFromConfig(config);
16
+ if (isSingleRuleListener(ruleOrRules)) {
17
+ return wrapSingleRuleListener(ruleOrRules, failSilently);
18
+ }
19
+ return wrapRuleListener(ruleOrRules, failSilently);
20
+ }
21
+ function isSingleRuleListener(rule) {
22
+ return typeof rule === 'function';
23
+ }
24
+ function failSilentlyFromConfig(c) {
25
+ switch (typeof c) {
26
+ case 'undefined':
27
+ return false;
28
+ case 'boolean':
29
+ return c;
30
+ case 'object':
31
+ if ('failSilently' in c) {
32
+ var _c$failSilently;
33
+ return (_c$failSilently = c.failSilently) !== null && _c$failSilently !== void 0 ? _c$failSilently : false;
34
+ } else if ('config' in c) {
35
+ var _c$config$failSilentl;
36
+ return (_c$config$failSilentl = c.config.failSilently) !== null && _c$config$failSilentl !== void 0 ? _c$config$failSilentl : false;
37
+ }
38
+ return false;
39
+ default:
40
+ throw new Error('Invalid config');
18
41
  }
19
- };
42
+ }
43
+ function wrapSingleRuleListener(rule, failSilently) {
44
+ return (...args) => {
45
+ try {
46
+ rule(...args);
47
+ } catch (err) {
48
+ if (!failSilently) {
49
+ // eslint-disable-next-line no-console
50
+ console.warn(err);
51
+ }
52
+ }
53
+ };
54
+ }
55
+ function wrapRuleListener(ruleListener, failSilently) {
56
+ return Object.entries(ruleListener).reduce((wrappedRuleListener, e) => {
57
+ const ruleName = e[0];
58
+ const rule = e[1];
59
+ return Object.assign(wrappedRuleListener, {
60
+ [ruleName]: wrapSingleRuleListener(rule, failSilently)
61
+ });
62
+ }, {});
63
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::9bb5329713677543f16019954484ae2f>>
3
+ * @codegen <<SignedSource::ab43b6e1a867d07b9a27eae78d48834a>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -12,6 +12,7 @@ export default {
12
12
  '@atlaskit/design-system/icon-label': 'warn',
13
13
  '@atlaskit/design-system/no-banned-imports': 'error',
14
14
  '@atlaskit/design-system/no-css-tagged-template-expression': 'error',
15
+ '@atlaskit/design-system/no-custom-icons': 'warn',
15
16
  '@atlaskit/design-system/no-deprecated-apis': 'error',
16
17
  '@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
17
18
  '@atlaskit/design-system/no-deprecated-imports': 'error',
@@ -490,7 +490,8 @@ var defaultConfig = {
490
490
  cssImportSource: CSS_IN_JS_IMPORTS.compiled,
491
491
  xcssImportSource: CSS_IN_JS_IMPORTS.atlaskitPrimitives,
492
492
  excludeReactComponents: false,
493
- autoFix: true
493
+ autoFix: true,
494
+ shouldAlwaysCheckXcss: false
494
495
  };
495
496
  var rule = createLintRule({
496
497
  meta: {
@@ -533,6 +534,9 @@ var rule = createLintRule({
533
534
  excludeReactComponents: {
534
535
  type: 'boolean'
535
536
  },
537
+ shouldAlwaysCheckXcss: {
538
+ type: 'boolean'
539
+ },
536
540
  autoFix: {
537
541
  type: 'boolean'
538
542
  }
@@ -547,7 +551,20 @@ var rule = createLintRule({
547
551
  var node = nodeOriginal;
548
552
  var name = node.name,
549
553
  value = node.value;
550
- if (mergedConfig.excludeReactComponents && node.parent.type === 'JSXOpeningElement') {
554
+
555
+ /**
556
+ * We skip linting `xcss` attributes if:
557
+ *
558
+ * - excludeReactComponents === true
559
+ * - shouldAlwaysCheckXcss === false
560
+ *
561
+ * In the future we may want to remove `shouldAlwaysCheckXcss`
562
+ * and just always lint `xcss`, regardless of `excludeReactComponents`
563
+ */
564
+ if (mergedConfig.excludeReactComponents && name.name === 'xcss' && !mergedConfig.shouldAlwaysCheckXcss) {
565
+ return;
566
+ }
567
+ if (mergedConfig.excludeReactComponents && node.parent.type === 'JSXOpeningElement' && name.name === 'css') {
551
568
  // e.g. <item.before />
552
569
  if (node.parent.name.type === 'JSXMemberExpression') {
553
570
  return;
@@ -29,26 +29,18 @@ var createWithConfig = function createWithConfig(initialConfig) {
29
29
  failSilently: (userConfig === null || userConfig === void 0 ? void 0 : userConfig.failSilently) || defaultConfig.failSilently
30
30
  };
31
31
  var tokenNode = null;
32
- return {
32
+ return errorBoundary({
33
33
  ImportDeclaration: function ImportDeclaration(node) {
34
- return errorBoundary(function () {
35
- if (node.source.value === '@atlaskit/tokens' && config.applyImport) {
36
- tokenNode = node;
37
- }
38
- }, {
39
- config: config
40
- });
34
+ if (node.source.value === '@atlaskit/tokens' && config.applyImport) {
35
+ tokenNode = node;
36
+ }
41
37
  },
42
38
  // For expressions within template literals (e.g. `color: ${red}`) - color only
43
39
  'TemplateLiteral > Identifier': function TemplateLiteralIdentifier(node) {
44
- return errorBoundary(function () {
45
- if (config.domains.includes('color')) {
46
- return lintTemplateIdentifierForColor(node, context, config);
47
- }
48
- return;
49
- }, {
50
- config: config
51
- });
40
+ if (config.domains.includes('color')) {
41
+ return lintTemplateIdentifierForColor(node, context, config);
42
+ }
43
+ return;
52
44
  },
53
45
  // const styles = css({ color: 'red', margin: '4px' }), styled.div({ color: 'red', margin: '4px' })
54
46
  ObjectExpression: function (_ObjectExpression) {
@@ -60,263 +52,243 @@ var createWithConfig = function createWithConfig(initialConfig) {
60
52
  };
61
53
  return ObjectExpression;
62
54
  }(function (parentNode) {
63
- return errorBoundary(function () {
64
- var _context$getScope = context.getScope(),
65
- references = _context$getScope.references;
66
- /**
67
- * NOTE: This rule doesn't have an `importSources` config option,
68
- * so this will just be equal to DEFAULT_IMPORT_SOURCES (which is fine)
69
- */
70
- var importSources = getImportSources(context);
55
+ var _context$getScope = context.getScope(),
56
+ references = _context$getScope.references;
57
+ /**
58
+ * NOTE: This rule doesn't have an `importSources` config option,
59
+ * so this will just be equal to DEFAULT_IMPORT_SOURCES (which is fine)
60
+ */
61
+ var importSources = getImportSources(context);
71
62
 
72
- // To force the correct node type
73
- if (!isNodeOfType(parentNode, 'ObjectExpression')) {
74
- return;
75
- }
63
+ // To force the correct node type
64
+ if (!isNodeOfType(parentNode, 'ObjectExpression')) {
65
+ return;
66
+ }
76
67
 
77
- // Return for nested objects - these get handled automatically so without returning we'd be doubling up
78
- if (parentNode.parent.type === 'Property') {
68
+ // Return for nested objects - these get handled automatically so without returning we'd be doubling up
69
+ if (parentNode.parent.type === 'Property') {
70
+ return;
71
+ }
72
+ if (isDecendantOfXcssBlock(parentNode, references, importSources)) {
73
+ return;
74
+ }
75
+ if (!isDecendantOfStyleBlock(parentNode) && !isDecendantOfType(parentNode, 'JSXExpressionContainer')) {
76
+ return;
77
+ }
78
+ function findObjectStyles(node) {
79
+ if (!isNodeOfType(node, 'Property')) {
79
80
  return;
80
81
  }
81
- if (isDecendantOfXcssBlock(parentNode, references, importSources)) {
82
+ if (isNodeOfType(node.value, 'ObjectExpression')) {
83
+ return node.value.properties.forEach(findObjectStyles);
84
+ }
85
+ if (!isNodeOfType(node.key, 'Identifier') && !isNodeOfType(node.key, 'Literal')) {
82
86
  return;
83
87
  }
84
- if (!isDecendantOfStyleBlock(parentNode) && !isDecendantOfType(parentNode, 'JSXExpressionContainer')) {
88
+ var propertyName = isNodeOfType(node.key, 'Identifier') ? node.key.name : String(node.key.value);
89
+
90
+ // Returns which domains to lint against based on rule's config and current property
91
+ var domains = getDomainsForProperty(propertyName, config.domains);
92
+ if (domains.length === 0 || isDecendantOfGlobalToken(node.value)) {
85
93
  return;
86
94
  }
87
- function findObjectStyles(node) {
88
- if (!isNodeOfType(node, 'Property')) {
89
- return;
90
- }
91
- if (isNodeOfType(node.value, 'ObjectExpression')) {
92
- return node.value.properties.forEach(findObjectStyles);
93
- }
94
- if (!isNodeOfType(node.key, 'Identifier') && !isNodeOfType(node.key, 'Literal')) {
95
- return;
95
+ if (isNodeOfType(node.value, 'TemplateLiteral')) {
96
+ var value = getValueFromTemplateLiteralRaw(node.value, context);
97
+ if (Array.isArray(value) && value.some(isCalc)) {
98
+ return context.report({
99
+ node: node,
100
+ messageId: 'noCalcUsage',
101
+ data: {
102
+ payload: "".concat(propertyName)
103
+ }
104
+ });
96
105
  }
97
- var propertyName = isNodeOfType(node.key, 'Identifier') ? node.key.name : String(node.key.value);
98
-
99
- // Returns which domains to lint against based on rule's config and current property
100
- var domains = getDomainsForProperty(propertyName, config.domains);
101
- if (domains.length === 0 || isDecendantOfGlobalToken(node.value)) {
106
+ if (node.value.expressions.some(isDecendantOfGlobalToken)) {
102
107
  return;
103
108
  }
104
- if (isNodeOfType(node.value, 'TemplateLiteral')) {
105
- var value = getValueFromTemplateLiteralRaw(node.value, context);
106
- if (Array.isArray(value) && value.some(isCalc)) {
107
- return context.report({
108
- node: node,
109
- messageId: 'noCalcUsage',
110
- data: {
111
- payload: "".concat(propertyName)
112
- }
113
- });
114
- }
115
- if (node.value.expressions.some(isDecendantOfGlobalToken)) {
116
- return;
117
- }
118
- }
119
- if (domains.includes('color')) {
120
- return lintObjectForColor(node, context, config);
121
- }
122
- if (domains.includes('spacing') || domains.includes('shape')) {
123
- /**
124
- * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration.
125
- */
126
- var fontSizeNode = getPropertyNodeFromParent('fontSize', parentNode);
127
- var fontSize = fontSizeNode && getValueForPropertyNode(fontSizeNode, context);
128
- return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
129
- }
130
109
  }
131
- parentNode.properties.forEach(findObjectStyles);
132
- }, {
133
- config: config
134
- });
110
+ if (domains.includes('color')) {
111
+ return lintObjectForColor(node, context, config);
112
+ }
113
+ if (domains.includes('spacing') || domains.includes('shape')) {
114
+ /**
115
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration.
116
+ */
117
+ var fontSizeNode = getPropertyNodeFromParent('fontSize', parentNode);
118
+ var fontSize = fontSizeNode && getValueForPropertyNode(fontSizeNode, context);
119
+ return lintObjectForSpacing(node, context, config, fontSize, tokenNode);
120
+ }
121
+ }
122
+ parentNode.properties.forEach(findObjectStyles);
135
123
  }),
136
124
  // CSSTemplateLiteral and StyledTemplateLiteral
137
125
  // const cssTemplateLiteral = css`color: red; padding: 12px`;
138
126
  // const styledTemplateLiteral = styled.p`color: red; padding: 8px`;
139
127
  'TaggedTemplateExpression[tag.name="css"],TaggedTemplateExpression[tag.object.name="styled"],TaggedTemplateExpression[tag.callee.name="styled"]': function TaggedTemplateExpressionTagNameCssTaggedTemplateExpressionTagObjectNameStyledTaggedTemplateExpressionTagCalleeNameStyled(node) {
140
- return errorBoundary(function () {
141
- // To force the correct node type
142
- if (!isNodeOfType(node, 'TaggedTemplateExpression')) {
143
- return;
144
- }
145
- var processedCssLines = processCssNode(node, context);
146
- if (!processedCssLines) {
147
- // if we can't get a processed css we bail
148
- return;
128
+ // To force the correct node type
129
+ if (!isNodeOfType(node, 'TaggedTemplateExpression')) {
130
+ return;
131
+ }
132
+ var processedCssLines = processCssNode(node, context);
133
+ if (!processedCssLines) {
134
+ // if we can't get a processed css we bail
135
+ return;
136
+ }
137
+ var globalFontSize = getFontSizeValueInScope(processedCssLines);
138
+ var textForSource = context.getSourceCode().getText(node.quasi);
139
+ var allReplacedValues = [];
140
+ var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
141
+ var _ref2 = _slicedToArray(_ref, 2),
142
+ resolvedCssLine = _ref2[0],
143
+ originalCssLine = _ref2[1];
144
+ var _resolvedCssLine$spli = resolvedCssLine.split(':'),
145
+ _resolvedCssLine$spli2 = _slicedToArray(_resolvedCssLine$spli, 2),
146
+ originalProperty = _resolvedCssLine$spli2[0],
147
+ resolvedCssValues = _resolvedCssLine$spli2[1];
148
+ var _originalCssLine$spli = originalCssLine.split(':'),
149
+ _originalCssLine$spli2 = _slicedToArray(_originalCssLine$spli, 2),
150
+ _ = _originalCssLine$spli2[0],
151
+ originalCssValues = _originalCssLine$spli2[1];
152
+ var propertyName = convertHyphenatedNameToCamelCase(originalProperty);
153
+ var isFontFamily = /fontFamily/.test(propertyName);
154
+ var replacedValuesPerProperty = [originalProperty];
155
+ var domains = getDomainsForProperty(propertyName, config.domains);
156
+ if (domains.length === 0 || !resolvedCssValues) {
157
+ // in both of these cases no changes should be made to the current property
158
+ return currentSource;
149
159
  }
150
- var globalFontSize = getFontSizeValueInScope(processedCssLines);
151
- var textForSource = context.getSourceCode().getText(node.quasi);
152
- var allReplacedValues = [];
153
- var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
154
- var _ref2 = _slicedToArray(_ref, 2),
155
- resolvedCssLine = _ref2[0],
156
- originalCssLine = _ref2[1];
157
- var _resolvedCssLine$spli = resolvedCssLine.split(':'),
158
- _resolvedCssLine$spli2 = _slicedToArray(_resolvedCssLine$spli, 2),
159
- originalProperty = _resolvedCssLine$spli2[0],
160
- resolvedCssValues = _resolvedCssLine$spli2[1];
161
- var _originalCssLine$spli = originalCssLine.split(':'),
162
- _originalCssLine$spli2 = _slicedToArray(_originalCssLine$spli, 2),
163
- _ = _originalCssLine$spli2[0],
164
- originalCssValues = _originalCssLine$spli2[1];
165
- var propertyName = convertHyphenatedNameToCamelCase(originalProperty);
166
- var isFontFamily = /fontFamily/.test(propertyName);
167
- var replacedValuesPerProperty = [originalProperty];
168
- var domains = getDomainsForProperty(propertyName, config.domains);
169
- if (domains.length === 0 || !resolvedCssValues) {
170
- // in both of these cases no changes should be made to the current property
160
+ if (domains.includes('color')) {
161
+ if (includesTokenString(resolvedCssValues.trim())) {
171
162
  return currentSource;
172
163
  }
173
- if (domains.includes('color')) {
174
- if (includesTokenString(resolvedCssValues.trim())) {
175
- return currentSource;
176
- }
177
- if (includesHardCodedColor(resolvedCssValues)) {
178
- context.report({
179
- messageId: 'hardCodedColor',
180
- node: node
181
- });
182
- return currentSource;
183
- }
164
+ if (includesHardCodedColor(resolvedCssValues)) {
165
+ context.report({
166
+ messageId: 'hardCodedColor',
167
+ node: node
168
+ });
169
+ return currentSource;
170
+ }
171
+ }
172
+ if (domains.includes('spacing') || domains.includes('shape')) {
173
+ if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
174
+ // no changes should be made to the current property
175
+ return currentSource;
184
176
  }
185
- if (domains.includes('spacing') || domains.includes('shape')) {
186
- if (!isValidSpacingValue(resolvedCssValues, globalFontSize)) {
187
- // no changes should be made to the current property
188
- return currentSource;
189
- }
190
-
191
- // gets the values from the associated property, numeric values or NaN
192
- var processedNumericValues = getValueFromShorthand(resolvedCssValues);
193
- var processedValues = splitShorthandValues(resolvedCssValues);
194
- // only splits shorthand values but it does not transform NaNs so tokens are preserved
195
- var originalValues = splitShorthandValues(originalCssValues);
196
-
197
- // reconstructing the string
198
- // should replace what it can and preserve the raw value for everything else
199
177
 
200
- var replacementValue = processedNumericValues
201
- // put together resolved value and original value on a tuple
202
- .map(function (value, index) {
203
- return [
204
- // if emToPX conversion fails we'll default to original value
205
- emToPixels(value, globalFontSize) || value, processedValues[index], originalValues[index]];
206
- }).map(function (_ref3) {
207
- var _ref4 = _slicedToArray(_ref3, 3),
208
- numericOrNanValue = _ref4[0],
209
- pxValue = _ref4[1],
210
- originalValue = _ref4[2];
211
- if (!originalValue) {
212
- return originalValue;
213
- }
214
- if (isCalc(originalValue)) {
215
- context.report({
216
- node: node,
217
- messageId: 'noCalcUsage',
218
- data: {
219
- payload: "".concat(propertyName)
220
- }
221
- });
222
- return originalValue;
223
- }
224
- if (isTokenValueString(originalValue)) {
225
- // if the value is already valid, nothing to report or replace
226
- return originalValue;
227
- }
178
+ // gets the values from the associated property, numeric values or NaN
179
+ var processedNumericValues = getValueFromShorthand(resolvedCssValues);
180
+ var processedValues = splitShorthandValues(resolvedCssValues);
181
+ // only splits shorthand values but it does not transform NaNs so tokens are preserved
182
+ var originalValues = splitShorthandValues(originalCssValues);
228
183
 
229
- // do not replace 0 or auto with tokens
230
- if (isZero(pxValue) || isAuto(pxValue)) {
231
- return originalValue;
232
- }
233
- if (isNaN(numericOrNanValue) && !isFontFamily) {
234
- // do not report if we have nothing to replace with
235
- return originalValue;
236
- }
184
+ // reconstructing the string
185
+ // should replace what it can and preserve the raw value for everything else
237
186
 
238
- // value is numeric or fontFamily, and needs replacing we'll report first
187
+ var replacementValue = processedNumericValues
188
+ // put together resolved value and original value on a tuple
189
+ .map(function (value, index) {
190
+ return [
191
+ // if emToPX conversion fails we'll default to original value
192
+ emToPixels(value, globalFontSize) || value, processedValues[index], originalValues[index]];
193
+ }).map(function (_ref3) {
194
+ var _ref4 = _slicedToArray(_ref3, 3),
195
+ numericOrNanValue = _ref4[0],
196
+ pxValue = _ref4[1],
197
+ originalValue = _ref4[2];
198
+ if (!originalValue) {
199
+ return originalValue;
200
+ }
201
+ if (isCalc(originalValue)) {
239
202
  context.report({
240
203
  node: node,
241
- messageId: 'noRawSpacingValues',
204
+ messageId: 'noCalcUsage',
242
205
  data: {
243
- payload: "".concat(propertyName, ":").concat(numericOrNanValue)
206
+ payload: "".concat(propertyName)
244
207
  }
245
208
  });
209
+ return originalValue;
210
+ }
211
+ if (isTokenValueString(originalValue)) {
212
+ // if the value is already valid, nothing to report or replace
213
+ return originalValue;
214
+ }
246
215
 
247
- // from here on we know value is numeric or a font family, so it might or might not have a token equivalent
248
- var replacementNode = getTokenReplacement(propertyName, numericOrNanValue);
249
- if (!replacementNode) {
250
- return originalValue;
251
- }
252
- var replacementToken = '${' + replacementNode.toString() + '}';
253
- replacedValuesPerProperty.push(isFontFamily ? numericOrNanValue.trim() : pxValue);
254
- return replacementToken;
255
- }).join(' ');
256
- if (replacedValuesPerProperty.length > 1) {
257
- // first value is the property name, so it will always have at least 1
258
- allReplacedValues.push(replacedValuesPerProperty);
216
+ // do not replace 0 or auto with tokens
217
+ if (isZero(pxValue) || isAuto(pxValue)) {
218
+ return originalValue;
219
+ }
220
+ if (isNaN(numericOrNanValue) && !isFontFamily) {
221
+ // do not report if we have nothing to replace with
222
+ return originalValue;
259
223
  }
260
224
 
261
- // replace property:val with new property:val
262
- var replacedCssLine = currentSource.replace(originalCssLine, // padding: ${gridSize()}px;
263
- "".concat(originalProperty, ": ").concat(replacementValue));
264
- if (!replacedCssLine) {
265
- return currentSource;
225
+ // value is numeric or fontFamily, and needs replacing we'll report first
226
+ context.report({
227
+ node: node,
228
+ messageId: 'noRawSpacingValues',
229
+ data: {
230
+ payload: "".concat(propertyName, ":").concat(numericOrNanValue)
231
+ }
232
+ });
233
+
234
+ // from here on we know value is numeric or a font family, so it might or might not have a token equivalent
235
+ var replacementNode = getTokenReplacement(propertyName, numericOrNanValue);
236
+ if (!replacementNode) {
237
+ return originalValue;
266
238
  }
267
- return replacedCssLine;
239
+ var replacementToken = '${' + replacementNode.toString() + '}';
240
+ replacedValuesPerProperty.push(isFontFamily ? numericOrNanValue.trim() : pxValue);
241
+ return replacementToken;
242
+ }).join(' ');
243
+ if (replacedValuesPerProperty.length > 1) {
244
+ // first value is the property name, so it will always have at least 1
245
+ allReplacedValues.push(replacedValuesPerProperty);
268
246
  }
269
- return currentSource;
270
- }, textForSource);
271
- if (completeSource !== textForSource) {
272
- // means we found some replacement values, we'll give the option to fix them
273
247
 
274
- context.report({
275
- node: node,
276
- messageId: 'autofixesPossible',
277
- fix: function fix(fixer) {
278
- return (!tokenNode && config.applyImport ? [insertTokensImport(fixer)] : []).concat([fixer.replaceText(node.quasi, completeSource)]);
279
- }
280
- });
248
+ // replace property:val with new property:val
249
+ var replacedCssLine = currentSource.replace(originalCssLine, // padding: ${gridSize()}px;
250
+ "".concat(originalProperty, ": ").concat(replacementValue));
251
+ if (!replacedCssLine) {
252
+ return currentSource;
253
+ }
254
+ return replacedCssLine;
281
255
  }
282
- }, {
283
- config: config
284
- });
256
+ return currentSource;
257
+ }, textForSource);
258
+ if (completeSource !== textForSource) {
259
+ // means we found some replacement values, we'll give the option to fix them
260
+
261
+ context.report({
262
+ node: node,
263
+ messageId: 'autofixesPossible',
264
+ fix: function fix(fixer) {
265
+ return (!tokenNode && config.applyImport ? [insertTokensImport(fixer)] : []).concat([fixer.replaceText(node.quasi, completeSource)]);
266
+ }
267
+ });
268
+ }
285
269
  },
286
270
  // For inline JSX styles - literals (e.g. <Test color="red"/>) - color only
287
271
  'JSXAttribute > Literal': function JSXAttributeLiteral(node) {
288
- return errorBoundary(function () {
289
- if (config.domains.includes('color')) {
290
- return lintJSXLiteralForColor(node, context, config);
291
- }
292
- return;
293
- }, {
294
- config: config
295
- });
272
+ if (config.domains.includes('color')) {
273
+ return lintJSXLiteralForColor(node, context, config);
274
+ }
275
+ return;
296
276
  },
297
277
  // For inline JSX styles - members (e.g. <Test color={color.red}/>) - color only
298
278
  'JSXExpressionContainer > MemberExpression': function JSXExpressionContainerMemberExpression(node) {
299
- return errorBoundary(function () {
300
- if (config.domains.includes('color')) {
301
- return lintJSXMemberForColor(node, context, config);
302
- }
303
- return;
304
- }, {
305
- config: config
306
- });
279
+ if (config.domains.includes('color')) {
280
+ return lintJSXMemberForColor(node, context, config);
281
+ }
282
+ return;
307
283
  },
308
284
  // For inline JSX styles - identifiers (e.g. <Test color={red}/>) - color only
309
285
  'JSXExpressionContainer > Identifier': function JSXExpressionContainerIdentifier(node) {
310
- return errorBoundary(function () {
311
- if (config.domains.includes('color')) {
312
- return lintJSXIdentifierForColor(node, context, config);
313
- }
314
- return;
315
- }, {
316
- config: config
317
- });
286
+ if (config.domains.includes('color')) {
287
+ return lintJSXIdentifierForColor(node, context, config);
288
+ }
289
+ return;
318
290
  }
319
- };
291
+ }, config);
320
292
  };
321
293
  };
322
294
  var rule = createLintRule({
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::b359d356c482db0087ddfce5bd105403>>
3
+ * @codegen <<SignedSource::402e6eb5433560b1032e5ed926bb5564>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
@@ -9,6 +9,7 @@ import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
9
9
  import iconLabel from './icon-label';
10
10
  import noBannedImports from './no-banned-imports';
11
11
  import noCssTaggedTemplateExpression from './no-css-tagged-template-expression';
12
+ import noCustomIcons from './no-custom-icons';
12
13
  import noDeprecatedApis from './no-deprecated-apis';
13
14
  import noDeprecatedDesignTokenUsage from './no-deprecated-design-token-usage';
14
15
  import noDeprecatedImports from './no-deprecated-imports';
@@ -50,6 +51,7 @@ export default {
50
51
  'icon-label': iconLabel,
51
52
  'no-banned-imports': noBannedImports,
52
53
  'no-css-tagged-template-expression': noCssTaggedTemplateExpression,
54
+ 'no-custom-icons': noCustomIcons,
53
55
  'no-deprecated-apis': noDeprecatedApis,
54
56
  'no-deprecated-design-token-usage': noDeprecatedDesignTokenUsage,
55
57
  'no-deprecated-imports': noDeprecatedImports,
@@ -0,0 +1,6 @@
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ export function hasProp(node, propName) {
3
+ return isNodeOfType(node.openingElement, 'JSXOpeningElement') && node.openingElement.attributes.some(function (a) {
4
+ return a.type === 'JSXAttribute' && a.name.name === propName;
5
+ });
6
+ }