@atlaskit/eslint-plugin-design-system 4.15.5 → 4.16.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 (31) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +56 -2
  3. package/configs/deprecated.json +33 -0
  4. package/dist/cjs/index.js +9 -1
  5. package/dist/cjs/rules/ensure-design-token-usage-spacing/index.js +105 -169
  6. package/dist/cjs/rules/ensure-design-token-usage-spacing/utils.js +192 -6
  7. package/dist/cjs/rules/no-deprecated-apis/helpers/filter-actionable-deprecations.js +59 -0
  8. package/dist/cjs/rules/no-deprecated-apis/helpers/validate-deprecated-apis-config.js +60 -0
  9. package/dist/cjs/rules/no-deprecated-apis/index.js +108 -32
  10. package/dist/cjs/version.json +1 -1
  11. package/dist/configs/deprecated.json +33 -0
  12. package/dist/es2019/index.js +2 -1
  13. package/dist/es2019/rules/ensure-design-token-usage-spacing/index.js +87 -147
  14. package/dist/es2019/rules/ensure-design-token-usage-spacing/utils.js +153 -4
  15. package/dist/es2019/rules/no-deprecated-apis/helpers/filter-actionable-deprecations.js +50 -0
  16. package/dist/es2019/rules/no-deprecated-apis/helpers/validate-deprecated-apis-config.js +54 -0
  17. package/dist/es2019/rules/no-deprecated-apis/index.js +98 -32
  18. package/dist/es2019/version.json +1 -1
  19. package/dist/esm/index.js +2 -1
  20. package/dist/esm/rules/ensure-design-token-usage-spacing/index.js +102 -166
  21. package/dist/esm/rules/ensure-design-token-usage-spacing/utils.js +175 -6
  22. package/dist/esm/rules/no-deprecated-apis/helpers/filter-actionable-deprecations.js +51 -0
  23. package/dist/esm/rules/no-deprecated-apis/helpers/validate-deprecated-apis-config.js +52 -0
  24. package/dist/esm/rules/no-deprecated-apis/index.js +104 -31
  25. package/dist/esm/version.json +1 -1
  26. package/dist/types/index.d.ts +4 -1
  27. package/dist/types/rules/ensure-design-token-usage-spacing/utils.d.ts +123 -1
  28. package/dist/types/rules/no-deprecated-apis/helpers/filter-actionable-deprecations.d.ts +1 -0
  29. package/dist/types/rules/no-deprecated-apis/helpers/validate-deprecated-apis-config.d.ts +2 -0
  30. package/dist/types/rules/no-deprecated-apis/index.d.ts +14 -2
  31. package/package.json +8 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 4.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`efadee8e999`](https://bitbucket.org/atlassian/atlassian-frontend/commits/efadee8e999) - Update no-deprecated-apis ESlint rule to accept configurations
8
+
9
+ ## 4.15.6
10
+
11
+ ### Patch Changes
12
+
13
+ - [`6a43a780a85`](https://bitbucket.org/atlassian/atlassian-frontend/commits/6a43a780a85) - Enhance token replacement capabilities of ensure-design-tokens-usage-spacing rule in tagged template literal strings
14
+
3
15
  ## 4.15.5
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -40,13 +40,67 @@ module.exports = {
40
40
  + '@atlaskit/design-system/no-unsafe-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
41
41
  + '@atlaskit/design-system/use-visually-hidden': 'error',
42
42
  + '@atlaskit/design-system/no-deprecated-imports': 'error',
43
- + '@atlaskit/design-system/no-deprecated-api-usage': 'error'
43
+ + '@atlaskit/design-system/no-deprecated-api': 'error',
44
44
  }
45
45
  }
46
46
  };
47
47
  ```
48
48
 
49
- Rules will where possible come with fixers.
49
+ ## Usage of '@atlaskit/design-system/no-deprecated-api'
50
+
51
+ You can use the `@atlaskit/design-system/no-deprecated-api` rule to check for deprecated API usage in your codebase. The rule can take one option - `deprecatedConfig`, if not provided, the rule will use the default config file. If provided, the rule will override the default config file and use the config file provided.
52
+ See the examples below:
53
+ [Usage with default deprecated APIs config](###Usage-with-default-deprecated-APIs-config)
54
+ [Overwrite default deprecated APIs config](###Overwrite-default-deprecated-APIs-config)
55
+
56
+ ### Default deprecated APIs config
57
+
58
+ The default config containing the deprecated APIs config for this rule. You can import the default config file from `@atlaskit/eslint-plugin-design-system`.
59
+
60
+ ```js
61
+ import { configs } from '@atlaskit/eslint-plugin-design-system';
62
+ const { deprecatedConfig } = configs;
63
+ ```
64
+
65
+ In the default config file you can find the following fields:
66
+
67
+ - `deprecatedAPI`, which is the deprecated props. Each prop has the following fields:
68
+
69
+ - `moduleSpecifier`, which is the module specifier of the package in which the prop was deprecated. For example: `@atlaskit/button`.
70
+ - `namedSpecifier`**(optional)**, which is an array of named specifiers of the package in which the prop was deprecated. For example: `Button`.
71
+ - `actionableVersion`**(optional)**, which is the version of the package in which the prop can be actioned on. For example: `1.0.0`.
72
+
73
+ ### Usage with default deprecated APIs config
74
+
75
+ Enable the rule as other rules if you want to use the default deprecated APIs config. The rule will automatically load the default config file and use it.
76
+
77
+ Enable the rule in your `.eslintrc.js` file:
78
+
79
+ ```js
80
+ rules: {
81
+ '@atlaskit/design-system/no-deprecated-api': 'error'
82
+ }
83
+ ```
84
+
85
+ ### Overwrite default deprecated APIs config
86
+
87
+ You can overwrite the default deprecated APIs to suits your needs. You can do this by providing the `deprecatedConfig` option to the rule. The option can be partial of the default config file, or a new config that contatins the required fields described in the [Default deprecated APIs config](###Default-deprecated-APIs-config) section.
88
+
89
+ The plugin also provides a `filterActionableDeprecations` util function that accepts the `deprecated APIs config` and `your root package.json` as params, and will filter the default deprecated APIs config based on the package versions listed in the package.json file, and return a list of actionable entries.
90
+ Example:
91
+
92
+ ```js
93
+ import { configs } from '@atlaskit/eslint-plugin-design-system';
94
+ import packageJson from '.path-to/package.json';
95
+
96
+ rules: {
97
+ '@atlaskit/design-system/no-deprecated-api': ['error', {
98
+ 'deprecatedConfig': filterActionableDeprecations(configs.deprecatedConfig, JSON.parse(packageJson)),
99
+ }]
100
+ }
101
+ ```
102
+
103
+ Rules may come with fixers to assist.
50
104
  For individual rules see the [`rules`](./src/rules) folder,
51
105
  however its strongly recommended to use the rules as above.
52
106
  You can read more about configuring eslint in their [documentation](https://eslint.org/docs/user-guide/configuring).
@@ -0,0 +1,33 @@
1
+ {
2
+ "cssFn": [{
3
+ "moduleSpecifier": "@atlaskit/menu"
4
+ },
5
+ {
6
+ "moduleSpecifier": "@atlaskit/side-navigation"
7
+ }
8
+ ],
9
+ "overrides": [{
10
+ "moduleSpecifier": "@atlaskit/menu"
11
+ },
12
+ {
13
+ "moduleSpecifier": "@atlaskit/side-navigation"
14
+ }
15
+ ],
16
+ "type": [{
17
+ "moduleSpecifier": "@atlaskit/inline-message"
18
+ }],
19
+ "textColor": [{
20
+ "moduleSpecifier": "@atlaskit/logo"
21
+
22
+ }],
23
+ "iconColor": [{
24
+ "moduleSpecifier": "@atlaskit/logo"
25
+ }],
26
+ "iconGradientStart": [{
27
+ "moduleSpecifier": "@atlaskit/logo"
28
+ }],
29
+ "iconGradientStop": [{
30
+ "moduleSpecifier": "@atlaskit/logo"
31
+ }]
32
+
33
+ }
package/dist/cjs/index.js CHANGED
@@ -4,7 +4,14 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.rules = exports.configs = void 0;
7
+ exports.configs = void 0;
8
+ Object.defineProperty(exports, "filterActionableDeprecations", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _filterActionableDeprecations.filterActionableDeprecations;
12
+ }
13
+ });
14
+ exports.rules = void 0;
8
15
  var _ensureDesignTokenUsage = _interopRequireDefault(require("./rules/ensure-design-token-usage"));
9
16
  var _ensureDesignTokenUsageSpacing = _interopRequireDefault(require("./rules/ensure-design-token-usage-spacing"));
10
17
  var _iconLabel = _interopRequireDefault(require("./rules/icon-label"));
@@ -14,6 +21,7 @@ var _noDeprecatedDesignTokenUsage = _interopRequireDefault(require("./rules/no-d
14
21
  var _noDeprecatedImports = _interopRequireDefault(require("./rules/no-deprecated-imports"));
15
22
  var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./rules/no-unsafe-design-token-usage"));
16
23
  var _useVisuallyHidden = _interopRequireDefault(require("./rules/use-visually-hidden"));
24
+ var _filterActionableDeprecations = require("./rules/no-deprecated-apis/helpers/filter-actionable-deprecations");
17
25
  var rules = {
18
26
  'ensure-design-token-usage': _ensureDesignTokenUsage.default,
19
27
  'icon-label': _iconLabel.default,
@@ -8,94 +8,10 @@ exports.default = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _eslintCodemodUtils = require("eslint-codemod-utils");
11
- var _tokensRaw = require("@atlaskit/tokens/tokens-raw");
12
11
  var _isNode = require("../utils/is-node");
13
12
  var _utils = require("./utils");
14
13
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
15
14
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
16
- /**
17
- * Currently we have a wide range of experimental spacing tokens that we are testing.
18
- * We only want transforms to apply to the stable scale values, not the rest.
19
- * This could be removed in the future.
20
- */
21
- var onlyScaleTokens = _tokensRaw.spacing.filter(function (token) {
22
- return token.name.startsWith('space.');
23
- });
24
- var spacingValueToToken = Object.fromEntries(onlyScaleTokens.map(function (token) {
25
- return [token.attributes['pixelValue'], token.name];
26
- }));
27
- var typographyValueToToken = Object.fromEntries(_tokensRaw.typography.map(function (currentToken) {
28
- // Group tokens by property name (e.g. fontSize, fontFamily, lineHeight)
29
- // This allows us to look up values specific to a property
30
- // (so as not to mix tokens with overlapping values e.g. font size and line height both have tokens for 16px)
31
- var tokenGroup = currentToken.attributes.group;
32
- return [tokenGroup, Object.fromEntries(_tokensRaw.typography.map(function (token) {
33
- return token.attributes.group === tokenGroup ? [token.value.replaceAll("\"", "'"), token.name] : [];
34
- }).filter(function (token) {
35
- return token.length;
36
- }))];
37
- }));
38
-
39
- /**
40
- * Returns a token node for a given value including fallbacks.
41
- * @param propertyName camelCase CSS property
42
- * @param value string representing pixel value, or font family, or number representing font weight
43
- * @example
44
- * ```
45
- * propertyName: padding, value: '8px' => token('space.100', '8px')
46
- * propertyName: fontWeight, value: 400 => token('font.weight.regular', '400')
47
- * ```
48
- */
49
- function getTokenNodeForValue(propertyName, value) {
50
- var token = (0, _utils.isTypographyProperty)(propertyName) ? typographyValueToToken[propertyName][value] : spacingValueToToken[value];
51
- var fallbackValue = propertyName === 'fontFamily' ? {
52
- value: "".concat(value),
53
- raw: "\"".concat(value, "\"")
54
- } : "".concat(value);
55
- return (0, _eslintCodemodUtils.callExpression)({
56
- callee: (0, _eslintCodemodUtils.identifier)({
57
- name: 'token'
58
- }),
59
- arguments: [(0, _eslintCodemodUtils.literal)({
60
- value: "'".concat(token !== null && token !== void 0 ? token : '', "'")
61
- }), (0, _eslintCodemodUtils.literal)(fallbackValue)],
62
- optional: false
63
- });
64
- }
65
-
66
- /**
67
- * Returns a boolean that signals wether the current property is revelant under the current configuration
68
- * @param propertyName camelCase CSS property
69
- * @param targetOptions Array containing the types of properties that should be included in the rule
70
- * @example
71
- * ```
72
- * propertyName: padding, targetOptions: ['spacing']
73
- * propertyName: fontWeight, targetOptions: ['spacing', 'typography']
74
- * ```
75
- */
76
- function shouldAnalyzeProperty(propertyName, targetOptions) {
77
- if ((0, _utils.isSpacingProperty)(propertyName) && targetOptions.includes('spacing')) {
78
- return true;
79
- }
80
- if ((0, _utils.isTypographyProperty)(propertyName) && targetOptions.includes('typography')) {
81
- return true;
82
- }
83
- return false;
84
- }
85
- /**
86
- * Attempts to remove all non-essential words & characters from a style block.
87
- * Including selectors and queries
88
- * Adapted from ensure-design-token-usage
89
- * @param styleString string of css properties
90
- */
91
- function splitCssProperties(styleString) {
92
- return styleString.split('\n').filter(function (line) {
93
- return !line.trim().startsWith('@');
94
- }).join('\n').replace(/\n/g, '').split(/;|(?<!\$){|(?<!\${.+?)}/) // don't split on template literal expressions i.e. `${...}`
95
- .map(function (el) {
96
- return el.trim() || '';
97
- }).filter(Boolean);
98
- }
99
15
  var rule = {
100
16
  meta: {
101
17
  type: 'problem',
@@ -105,7 +21,8 @@ var rule = {
105
21
  recommended: true
106
22
  },
107
23
  messages: {
108
- noRawSpacingValues: 'The use of spacing primitives or tokens is preferred over the direct application of spacing properties.\n\n@meta <<{{payload}}>>'
24
+ noRawSpacingValues: 'The use of spacing primitives or tokens is preferred over the direct application of spacing properties.\n\n@meta <<{{payload}}>>',
25
+ autofixesPossible: 'Automated corrections available for spacing values. Apply autofix to replace values with appropriate tokens'
109
26
  }
110
27
  },
111
28
  create: function create(context) {
@@ -149,7 +66,7 @@ var rule = {
149
66
  if (!(0, _eslintCodemodUtils.isNodeOfType)(node.key, 'Identifier')) {
150
67
  return;
151
68
  }
152
- if (!shouldAnalyzeProperty(node.key.name, targetCategories)) {
69
+ if (!(0, _utils.shouldAnalyzeProperty)(node.key.name, targetCategories)) {
153
70
  return;
154
71
  }
155
72
  if ((0, _isNode.isDecendantOfGlobalToken)(node.value)) {
@@ -198,16 +115,16 @@ var rule = {
198
115
  },
199
116
  fix: function fix(fixer) {
200
117
  var _node$loc;
201
- if (!shouldAnalyzeProperty(propertyName, targetCategories)) {
118
+ if (!(0, _utils.shouldAnalyzeProperty)(propertyName, targetCategories)) {
202
119
  return null;
203
120
  }
204
121
  var pixelValueString = "".concat(pixelValue, "px");
205
122
  var lookupValue = /fontWeight|fontFamily/.test(propertyName) ? pixelValue : pixelValueString;
206
- var tokenName = (0, _utils.isTypographyProperty)(propertyName) ? typographyValueToToken[propertyName][lookupValue] : spacingValueToToken[lookupValue];
123
+ var tokenName = (0, _utils.isTypographyProperty)(propertyName) ? _utils.typographyValueToToken[propertyName][lookupValue] : _utils.spacingValueToToken[lookupValue];
207
124
  if (!tokenName) {
208
125
  return null;
209
126
  }
210
- var replacementValue = getTokenNodeForValue(propertyName, lookupValue);
127
+ var replacementValue = (0, _utils.getTokenNodeForValue)(propertyName, lookupValue);
211
128
  return [fixer.insertTextBefore(node, "// TODO Delete this comment after verifying spacing token -> previous value `".concat((0, _eslintCodemodUtils.node)(node.value), "`\n").concat(' '.padStart(((_node$loc = node.loc) === null || _node$loc === void 0 ? void 0 : _node$loc.start.column) || 0))), fixer.replaceText(node, (0, _eslintCodemodUtils.property)(_objectSpread(_objectSpread({}, node), {}, {
212
129
  value: replacementValue
213
130
  })).toString())];
@@ -240,7 +157,7 @@ var rule = {
240
157
  return fixer.replaceText(node.value, "`".concat(values.map(function (value) {
241
158
  var pixelValue = (0, _utils.emToPixels)(value, fontSize);
242
159
  var pixelValueString = "".concat(pixelValue, "px");
243
- return "${".concat(getTokenNodeForValue(propertyName, pixelValueString), "}");
160
+ return "${".concat((0, _utils.getTokenNodeForValue)(propertyName, pixelValueString), "}");
244
161
  }).join(' '), "`"));
245
162
  } : undefined
246
163
  });
@@ -256,96 +173,115 @@ var rule = {
256
173
  return;
257
174
  }
258
175
  var parentNode = (0, _utils.findParentNodeForLine)(node);
259
- var combinedString = node.quasi.quasis.map(function (q, i) {
260
- return "".concat(q.value.raw).concat(node.quasi.expressions[i] ? (0, _utils.getValue)(node.quasi.expressions[i], context) : '');
261
- }).join('');
262
- var rawString = node.quasi.quasis.map(function (q, i) {
263
- return "".concat(q.value.raw).concat(node.quasi.expressions[i] ? "${".concat((0, _utils.getRawExpression)(node.quasi.expressions[i], context), "}") : '');
264
- }).join('');
265
- var cssProperties = splitCssProperties(combinedString);
266
- var unalteredCssProperties = splitCssProperties(rawString);
267
-
268
- // Get font size
269
- var fontSizeNode = cssProperties.find(function (style) {
270
- var _style$split = style.split(':'),
271
- _style$split2 = (0, _slicedToArray2.default)(_style$split, 2),
272
- rawProperty = _style$split2[0],
273
- value = _style$split2[1];
274
- return /font-size/.test(rawProperty) ? value : null;
275
- });
276
- var fontSize = (0, _utils.getValueFromShorthand)(fontSizeNode)[0];
277
- cssProperties.forEach(function (style, currentPropIndex) {
278
- var _style$split3 = style.split(':'),
279
- _style$split4 = (0, _slicedToArray2.default)(_style$split3, 2),
280
- rawProperty = _style$split4[0],
281
- value = _style$split4[1];
282
- var propertyName = (0, _utils.convertHyphenatedNameToCamelCase)(rawProperty);
283
- if (!shouldAnalyzeProperty(propertyName, targetCategories)) {
284
- return;
176
+ var processedCssLines = (0, _utils.processCssNode)(node, context);
177
+ var globalFontSize = (0, _utils.getFontSizeValueInScope)(processedCssLines);
178
+ var textForSource = context.getSourceCode().getText(node.quasi);
179
+ var allReplacedValues = [];
180
+ var completeSource = processedCssLines.reduce(function (currentSource, _ref) {
181
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
182
+ resolvedCssLine = _ref2[0],
183
+ originalCssLine = _ref2[1];
184
+ var _resolvedCssLine$spli = resolvedCssLine.split(':'),
185
+ _resolvedCssLine$spli2 = (0, _slicedToArray2.default)(_resolvedCssLine$spli, 2),
186
+ originalProperty = _resolvedCssLine$spli2[0],
187
+ resolvedCssValues = _resolvedCssLine$spli2[1];
188
+ var _originalCssLine$spli = originalCssLine.split(':'),
189
+ _originalCssLine$spli2 = (0, _slicedToArray2.default)(_originalCssLine$spli, 2),
190
+ _ = _originalCssLine$spli2[0],
191
+ originalCssValues = _originalCssLine$spli2[1];
192
+ var propertyName = (0, _utils.convertHyphenatedNameToCamelCase)(originalProperty);
193
+ var isFontFamily = /fontFamily/.test(propertyName);
194
+ var replacedValuesPerProperty = [originalProperty];
195
+ if (!(0, _utils.shouldAnalyzeProperty)(propertyName, targetCategories) || !resolvedCssValues || !(0, _utils.isValidSpacingValue)(resolvedCssValues, globalFontSize)) {
196
+ // in all of these cases no changes should be made to the current property
197
+ return currentSource;
285
198
  }
286
199
 
287
- // value is either NaN or it can't be resolved eg, em, 100% etc...
288
- if (!(0, _utils.isValidSpacingValue)(value, fontSize)) {
289
- return context.report({
290
- node: node,
291
- messageId: 'noRawSpacingValues',
292
- data: {
293
- payload: "NaN:".concat(value)
294
- }
295
- });
296
- }
297
- var values = (0, _utils.getValueFromShorthand)(value);
298
- values.forEach(function (val, index) {
299
- if (!val && val !== 0 || !shouldAnalyzeProperty(propertyName, targetCategories)) {
300
- return;
200
+ // gets the values from the associated property, numeric values or NaN
201
+ var processedNumericValues = (0, _utils.getValueFromShorthand)(resolvedCssValues);
202
+ var processedValues = (0, _utils.splitShorthandValues)(resolvedCssValues);
203
+ // only splits shorthand values but it does not transform NaNs so tokens are preserved
204
+ var originalValues = (0, _utils.splitShorthandValues)(originalCssValues);
205
+
206
+ // reconstructing the string
207
+ // should replace what it can and preserve the raw value for everything else
208
+
209
+ var replacementValue = processedNumericValues
210
+ // put together resolved value and original value on a tuple
211
+ .map(function (value, index) {
212
+ return [
213
+ // if emToPX conversion fails we'll default to original value
214
+ (0, _utils.emToPixels)(value, globalFontSize) || value, processedValues[index], originalValues[index]];
215
+ }).map(function (_ref3) {
216
+ var _ref4 = (0, _slicedToArray2.default)(_ref3, 3),
217
+ numericOrNanValue = _ref4[0],
218
+ pxValue = _ref4[1],
219
+ originalValue = _ref4[2];
220
+ if ((0, _utils.isTokenValueString)(originalValue)) {
221
+ // if the value is already valid, nothing to report or replace
222
+ return originalValue;
223
+ }
224
+ if (isNaN(numericOrNanValue) && !isFontFamily) {
225
+ // this can be either a weird expression or a fontsize declaration
226
+
227
+ // we can't replace a NaN but we can alert what the offending value is
228
+ context.report({
229
+ node: node,
230
+ messageId: 'noRawSpacingValues',
231
+ data: {
232
+ payload: "".concat(propertyName, ":").concat(originalValue)
233
+ }
234
+ });
235
+ return originalValue;
301
236
  }
302
- var isFontFamily = /fontFamily/.test(propertyName);
303
- var pixelValue = isFontFamily ? val : (0, _utils.emToPixels)(val, fontSize);
237
+
238
+ // value is numeric or fontFamily, and needs replacing we'll report first
304
239
  context.report({
305
240
  node: node,
306
241
  messageId: 'noRawSpacingValues',
307
242
  data: {
308
- payload: "".concat(propertyName, ":").concat(pixelValue)
309
- },
310
- fix: index === 0 ? function (fixer) {
311
- var allResolvableValues = values.every(function (value) {
312
- return !Number.isNaN((0, _utils.emToPixels)(value, fontSize));
313
- });
314
- if (!allResolvableValues) {
315
- return null;
316
- }
317
- var replacementValue = values.map(function (value) {
318
- var propertyValue = typeof value === 'string' ? value.trim() : value;
319
- var pixelValue = isFontFamily ? propertyValue : (0, _utils.emToPixels)(propertyValue, fontSize);
320
- var pixelValueString = "".concat(pixelValue, "px");
321
- var lookupValue = /fontWeight|fontFamily/.test(propertyName) ? pixelValue : pixelValueString;
322
- var tokenName = (0, _utils.isTypographyProperty)(propertyName) ? typographyValueToToken[propertyName][lookupValue] : spacingValueToToken[lookupValue];
323
- if (!tokenName) {
324
- return pixelValueString;
325
- }
326
- var replacementTokenValue = getTokenNodeForValue(propertyName, lookupValue);
243
+ payload: "".concat(propertyName, ":").concat(numericOrNanValue)
244
+ }
245
+ });
327
246
 
328
- // ${token('...', '...')}
329
- var replacementSubValue = '${' + replacementTokenValue.toString() + '}';
330
- return replacementSubValue;
331
- }).join(' ');
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 replacementToken = (0, _utils.getTokenReplacement)(propertyName, numericOrNanValue);
249
+ if (!replacementToken) {
250
+ return originalValue;
251
+ }
252
+ replacedValuesPerProperty.push(isFontFamily ? numericOrNanValue.trim() : pxValue);
253
+ return replacementToken;
254
+ }).join(' ');
255
+ if (replacedValuesPerProperty.length > 1) {
256
+ // first value is the property name, so it will always have at least 1
257
+ allReplacedValues.push(replacedValuesPerProperty);
258
+ }
332
259
 
333
- // get original source
334
- var textForSource = context.getSourceCode().getText(node.quasi);
260
+ // replace property:val with new property:val
261
+ var replacedCssLine = currentSource.replace(originalCssLine, // padding: ${gridSize()}px;
262
+ "".concat(originalProperty, ": ").concat(replacementValue));
263
+ if (!replacedCssLine) {
264
+ return currentSource;
265
+ }
266
+ return replacedCssLine;
267
+ }, textForSource);
268
+ if (completeSource !== textForSource) {
269
+ // means we found some replacement values, well give the option to fix them
335
270
 
336
- // find `<property>: ...;` in original
337
- var styleString = unalteredCssProperties[currentPropIndex];
338
- // replace property:val with new property:val
339
- var replacement = textForSource.replace(styleString, // padding: ${gridSize()}px;
340
- "".concat(rawProperty, ": ").concat(replacementValue));
341
- if (!replacement) {
342
- return [];
343
- }
344
- return [fixer.insertTextBefore(parentNode, "// TODO Delete this comment after verifying spacing token -> previous value `".concat(value.trim(), "`\n")), fixer.replaceText(node.quasi, replacement)];
345
- } : undefined
346
- });
271
+ var replacementComments = "".concat(allReplacedValues.map(function (replacedProperties) {
272
+ var _replacedProperties = (0, _slicedToArray2.default)(replacedProperties, 1),
273
+ propertyName = _replacedProperties[0];
274
+ var replacedValues = replacedProperties.slice(1).join(' ');
275
+ return "// TODO Delete this comment after verifying spacing token -> previous value `".concat(propertyName, ": ").concat(replacedValues, "`");
276
+ }).join('\n'), "\n");
277
+ context.report({
278
+ node: node,
279
+ messageId: 'autofixesPossible',
280
+ fix: function fix(fixer) {
281
+ return [fixer.insertTextBefore(parentNode, replacementComments), fixer.replaceText(node.quasi, completeSource)];
282
+ }
347
283
  });
348
- });
284
+ }
349
285
  }
350
286
  };
351
287
  }