@atlaskit/eslint-plugin-design-system 4.10.0 → 4.10.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-design-system
2
2
 
3
+ ## 4.10.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`d76851b2f42`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d76851b2f42) - Improved NaN handling and output
8
+ - [`0544fe823d1`](https://bitbucket.org/atlassian/atlassian-frontend/commits/0544fe823d1) - Updates to account for nested unary selectors.
9
+ - [`1ed3db0c9be`](https://bitbucket.org/atlassian/atlassian-frontend/commits/1ed3db0c9be) - Improvements to lint rule and accounting for edge cases
10
+
3
11
  ## 4.10.0
4
12
 
5
13
  ### Minor Changes
@@ -13,6 +13,12 @@ var _eslintCodemodUtils = require("eslint-codemod-utils");
13
13
 
14
14
  var _utils = require("./utils");
15
15
 
16
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
17
+
18
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
19
+
20
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
21
+
16
22
  var rule = {
17
23
  meta: {
18
24
  type: 'problem',
@@ -33,7 +39,7 @@ var rule = {
33
39
  return;
34
40
  }
35
41
  /**
36
- * We do this in case we the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
42
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
37
43
  */
38
44
 
39
45
 
@@ -64,26 +70,36 @@ var rule = {
64
70
  return;
65
71
  }
66
72
 
73
+ if (node.value.type === 'Literal' && !(0, _utils.isValidSpacingValue)(node.value.value, fontSize)) {
74
+ context.report({
75
+ node: node,
76
+ messageId: 'noRawSpacingValues',
77
+ data: {
78
+ payload: "NaN:".concat(node.value.value)
79
+ }
80
+ });
81
+ return;
82
+ }
83
+
67
84
  var value = (0, _utils.getValue)(node.value, context);
68
85
 
69
- if (value) {
86
+ if (value && (0, _utils.isValidSpacingValue)(value, fontSize)) {
70
87
  var values = typeof value === 'number' || typeof value === 'string' ? [value] : value;
71
- values.forEach(function (value) {
88
+ values.forEach(function (val) {
72
89
  context.report({
73
90
  node: node,
74
91
  messageId: 'noRawSpacingValues',
75
92
  data: {
76
- payload: "".concat(node.key.name, ":").concat((0, _utils.emToPixels)(value, fontSize))
93
+ payload: "".concat(node.key.name, ":").concat((0, _utils.emToPixels)(val, fontSize))
77
94
  }
78
95
  });
79
96
  });
80
- return;
81
97
  } else {
82
98
  context.report({
83
99
  node: node,
84
100
  messageId: 'noRawSpacingValues',
85
101
  data: {
86
- payload: "".concat(node.key.name, ":NaN")
102
+ payload: "NaN:".concat(value)
87
103
  }
88
104
  });
89
105
  }
@@ -106,7 +122,9 @@ var rule = {
106
122
  * Adapted from ensure-design-token-usage
107
123
  */
108
124
 
109
- var cssProperties = combinedString.replace(/\n/g, '').split(/;|{|}/).map(function (el) {
125
+ var cssProperties = combinedString.split('\n').filter(function (line) {
126
+ return !line.trim().startsWith('@');
127
+ }).join('\n').replace(/\n/g, '').split(/;|{|}/).map(function (el) {
110
128
  return el.trim() || '';
111
129
  });
112
130
  cssProperties.map(function (style) {
@@ -115,14 +133,41 @@ var rule = {
115
133
  property = _style$split2[0],
116
134
  value = _style$split2[1];
117
135
 
136
+ property = (0, _utils.convertHyphenatedNameToCamelCase)(property);
137
+
118
138
  if ((0, _utils.isSpacingProperty)(property)) {
119
- context.report({
120
- node: node,
121
- messageId: 'noRawSpacingValues',
122
- data: {
123
- payload: "".concat(property, ":").concat((0, _utils.removePixelSuffix)(value.trim()))
139
+ if ((0, _utils.isValidSpacingValue)(value)) {
140
+ var values = (0, _utils.getValueFromShorthand)(value);
141
+
142
+ var _iterator = _createForOfIteratorHelper(values),
143
+ _step;
144
+
145
+ try {
146
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
147
+ var val = _step.value;
148
+ // could be array of values e.g. padding: 8px 12px 3px
149
+ context.report({
150
+ node: node,
151
+ messageId: 'noRawSpacingValues',
152
+ data: {
153
+ payload: "".concat(property, ":").concat(val)
154
+ }
155
+ });
156
+ }
157
+ } catch (err) {
158
+ _iterator.e(err);
159
+ } finally {
160
+ _iterator.f();
124
161
  }
125
- });
162
+ } else {
163
+ context.report({
164
+ node: node,
165
+ messageId: 'noRawSpacingValues',
166
+ data: {
167
+ payload: "NaN:".concat(value)
168
+ }
169
+ });
170
+ }
126
171
  }
127
172
 
128
173
  return;
@@ -3,13 +3,13 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.emToPixels = void 0;
6
+ exports.emToPixels = exports.convertHyphenatedNameToCamelCase = void 0;
7
7
  exports.findIdentifierInParentScope = findIdentifierInParentScope;
8
- exports.removePixelSuffix = exports.isSpacingProperty = exports.getValueFromShorthand = exports.getValue = void 0;
8
+ exports.removePixelSuffix = exports.isValidSpacingValue = exports.isSpacingProperty = exports.getValueFromShorthand = exports.getValue = void 0;
9
9
 
10
10
  var _eslintCodemodUtils = require("eslint-codemod-utils");
11
11
 
12
- var properties = ['padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'margin', 'gap', 'fontSize', 'lineHeight', 'width', 'height'];
12
+ var properties = ['padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'margin', 'gap', 'fontSize', 'lineHeight', 'width', 'height', 'rowGap', 'gridRowGap', 'columnGap', 'gridColumnGap'];
13
13
 
14
14
  function findIdentifierInParentScope(_ref) {
15
15
  var scope = _ref.scope,
@@ -123,6 +123,10 @@ var getValueFromIdentifier = function getValueFromIdentifier(node, context) {
123
123
 
124
124
  var definition = variable.defs[0];
125
125
 
126
+ if ((0, _eslintCodemodUtils.isNodeOfType)(definition.node, 'ImportSpecifier') && (0, _eslintCodemodUtils.isNodeOfType)(definition.node.parent, 'ImportDeclaration') && definition.node.parent.source.value === '@atlassian/jira-common-legacy-do-not-add-anything-new/src/styles') {
127
+ return definition.node.imported.name === 'gridSize' ? 8 : null;
128
+ }
129
+
126
130
  if (!(0, _eslintCodemodUtils.isNodeOfType)(definition.node, 'VariableDeclarator')) {
127
131
  return null;
128
132
  }
@@ -146,7 +150,7 @@ var getValueFromUnaryExpression = function getValueFromUnaryExpression(node, con
146
150
  } // eslint-disable-next-line no-eval
147
151
 
148
152
 
149
- return eval("".concat(node.operator).concat(value));
153
+ return eval("".concat(node.operator, "(").concat(value, ")"));
150
154
  };
151
155
  /**
152
156
  * @example
@@ -198,9 +202,9 @@ var emToPixels = function emToPixels(value, fontSize) {
198
202
 
199
203
  if (match && typeof fontSize === 'number') {
200
204
  return Number(match[1]) * fontSize;
205
+ } else {
206
+ return null;
201
207
  }
202
-
203
- return 'NaN';
204
208
  }
205
209
 
206
210
  return value;
@@ -220,4 +224,37 @@ var removePixelSuffix = function removePixelSuffix(value) {
220
224
  return Number(isString ? value.replace('px', '') : value);
221
225
  };
222
226
 
223
- exports.removePixelSuffix = removePixelSuffix;
227
+ exports.removePixelSuffix = removePixelSuffix;
228
+ var invalidSpacingUnitRegex = /(%$)|(\d+rem$)|(^calc)|(vw$)|(vh$)/;
229
+
230
+ var isValidSpacingValue = function isValidSpacingValue(value, fontSize) {
231
+ if (typeof value === 'string') {
232
+ if (invalidSpacingUnitRegex.test(value)) {
233
+ return false;
234
+ }
235
+ } else if (Array.isArray(value)) {
236
+ // could be array due to shorthand
237
+ for (var val in value) {
238
+ if (invalidSpacingUnitRegex.test(val)) {
239
+ return false;
240
+ }
241
+ }
242
+ }
243
+
244
+ if (emRegex.test(value) && typeof fontSize !== 'number') {
245
+ return false;
246
+ }
247
+
248
+ return true;
249
+ }; // convert line-height to lineHeight
250
+
251
+
252
+ exports.isValidSpacingValue = isValidSpacingValue;
253
+
254
+ var convertHyphenatedNameToCamelCase = function convertHyphenatedNameToCamelCase(prop) {
255
+ return prop.replace(/-./g, function (m) {
256
+ return m[1].toUpperCase();
257
+ });
258
+ };
259
+
260
+ exports.convertHyphenatedNameToCamelCase = convertHyphenatedNameToCamelCase;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
- "version": "4.10.0",
3
+ "version": "4.10.1",
4
4
  "sideEffects": false
5
5
  }
@@ -1,5 +1,5 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
- import { emToPixels, getValue, isSpacingProperty, removePixelSuffix } from './utils';
2
+ import { convertHyphenatedNameToCamelCase, emToPixels, getValue, getValueFromShorthand, isSpacingProperty, isValidSpacingValue } from './utils';
3
3
  const rule = {
4
4
  meta: {
5
5
  type: 'problem',
@@ -21,7 +21,7 @@ const rule = {
21
21
  return;
22
22
  }
23
23
  /**
24
- * We do this in case we the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
24
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
25
25
  */
26
26
 
27
27
 
@@ -52,26 +52,36 @@ const rule = {
52
52
  return;
53
53
  }
54
54
 
55
+ if (node.value.type === 'Literal' && !isValidSpacingValue(node.value.value, fontSize)) {
56
+ context.report({
57
+ node,
58
+ messageId: 'noRawSpacingValues',
59
+ data: {
60
+ payload: `NaN:${node.value.value}`
61
+ }
62
+ });
63
+ return;
64
+ }
65
+
55
66
  const value = getValue(node.value, context);
56
67
 
57
- if (value) {
68
+ if (value && isValidSpacingValue(value, fontSize)) {
58
69
  const values = typeof value === 'number' || typeof value === 'string' ? [value] : value;
59
- values.forEach(value => {
70
+ values.forEach(val => {
60
71
  context.report({
61
72
  node,
62
73
  messageId: 'noRawSpacingValues',
63
74
  data: {
64
- payload: `${node.key.name}:${emToPixels(value, fontSize)}`
75
+ payload: `${node.key.name}:${emToPixels(val, fontSize)}`
65
76
  }
66
77
  });
67
78
  });
68
- return;
69
79
  } else {
70
80
  context.report({
71
81
  node,
72
82
  messageId: 'noRawSpacingValues',
73
83
  data: {
74
- payload: `${node.key.name}:NaN`
84
+ payload: `NaN:${value}`
75
85
  }
76
86
  });
77
87
  }
@@ -94,18 +104,34 @@ const rule = {
94
104
  * Adapted from ensure-design-token-usage
95
105
  */
96
106
 
97
- const cssProperties = combinedString.replace(/\n/g, '').split(/;|{|}/).map(el => el.trim() || '');
107
+ const cssProperties = combinedString.split('\n').filter(line => !line.trim().startsWith('@')).join('\n').replace(/\n/g, '').split(/;|{|}/).map(el => el.trim() || '');
98
108
  cssProperties.map(style => {
99
- const [property, value] = style.split(':');
109
+ let [property, value] = style.split(':');
110
+ property = convertHyphenatedNameToCamelCase(property);
100
111
 
101
112
  if (isSpacingProperty(property)) {
102
- context.report({
103
- node,
104
- messageId: 'noRawSpacingValues',
105
- data: {
106
- payload: `${property}:${removePixelSuffix(value.trim())}`
113
+ if (isValidSpacingValue(value)) {
114
+ const values = getValueFromShorthand(value);
115
+
116
+ for (const val of values) {
117
+ // could be array of values e.g. padding: 8px 12px 3px
118
+ context.report({
119
+ node,
120
+ messageId: 'noRawSpacingValues',
121
+ data: {
122
+ payload: `${property}:${val}`
123
+ }
124
+ });
107
125
  }
108
- });
126
+ } else {
127
+ context.report({
128
+ node,
129
+ messageId: 'noRawSpacingValues',
130
+ data: {
131
+ payload: `NaN:${value}`
132
+ }
133
+ });
134
+ }
109
135
  }
110
136
 
111
137
  return;
@@ -1,5 +1,5 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
- const properties = ['padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'margin', 'gap', 'fontSize', 'lineHeight', 'width', 'height'];
2
+ const properties = ['padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'margin', 'gap', 'fontSize', 'lineHeight', 'width', 'height', 'rowGap', 'gridRowGap', 'columnGap', 'gridColumnGap'];
3
3
  export function findIdentifierInParentScope({
4
4
  scope,
5
5
  identifierName
@@ -97,6 +97,10 @@ const getValueFromIdentifier = (node, context) => {
97
97
 
98
98
  const definition = variable.defs[0];
99
99
 
100
+ if (isNodeOfType(definition.node, 'ImportSpecifier') && isNodeOfType(definition.node.parent, 'ImportDeclaration') && definition.node.parent.source.value === '@atlassian/jira-common-legacy-do-not-add-anything-new/src/styles') {
101
+ return definition.node.imported.name === 'gridSize' ? 8 : null;
102
+ }
103
+
100
104
  if (!isNodeOfType(definition.node, 'VariableDeclarator')) {
101
105
  return null;
102
106
  }
@@ -120,7 +124,7 @@ const getValueFromUnaryExpression = (node, context) => {
120
124
  } // eslint-disable-next-line no-eval
121
125
 
122
126
 
123
- return eval(`${node.operator}${value}`);
127
+ return eval(`${node.operator}(${value})`);
124
128
  };
125
129
  /**
126
130
  * @example
@@ -173,9 +177,9 @@ export const emToPixels = (value, fontSize) => {
173
177
 
174
178
  if (match && typeof fontSize === 'number') {
175
179
  return Number(match[1]) * fontSize;
180
+ } else {
181
+ return null;
176
182
  }
177
-
178
- return 'NaN';
179
183
  }
180
184
 
181
185
  return value;
@@ -190,4 +194,29 @@ export const removePixelSuffix = value => {
190
194
 
191
195
 
192
196
  return Number(isString ? value.replace('px', '') : value);
197
+ };
198
+ const invalidSpacingUnitRegex = /(%$)|(\d+rem$)|(^calc)|(vw$)|(vh$)/;
199
+ export const isValidSpacingValue = (value, fontSize) => {
200
+ if (typeof value === 'string') {
201
+ if (invalidSpacingUnitRegex.test(value)) {
202
+ return false;
203
+ }
204
+ } else if (Array.isArray(value)) {
205
+ // could be array due to shorthand
206
+ for (const val in value) {
207
+ if (invalidSpacingUnitRegex.test(val)) {
208
+ return false;
209
+ }
210
+ }
211
+ }
212
+
213
+ if (emRegex.test(value) && typeof fontSize !== 'number') {
214
+ return false;
215
+ }
216
+
217
+ return true;
218
+ }; // convert line-height to lineHeight
219
+
220
+ export const convertHyphenatedNameToCamelCase = prop => {
221
+ return prop.replace(/-./g, m => m[1].toUpperCase());
193
222
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
- "version": "4.10.0",
3
+ "version": "4.10.1",
4
4
  "sideEffects": false
5
5
  }
@@ -1,6 +1,13 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+
3
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
4
+
5
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
6
+
7
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
8
+
2
9
  import { isNodeOfType } from 'eslint-codemod-utils';
3
- import { emToPixels, getValue, isSpacingProperty, removePixelSuffix } from './utils';
10
+ import { convertHyphenatedNameToCamelCase, emToPixels, getValue, getValueFromShorthand, isSpacingProperty, isValidSpacingValue } from './utils';
4
11
  var rule = {
5
12
  meta: {
6
13
  type: 'problem',
@@ -21,7 +28,7 @@ var rule = {
21
28
  return;
22
29
  }
23
30
  /**
24
- * We do this in case we the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
31
+ * We do this in case the fontSize for a style object is declared alongside the `em` or `lineHeight` declaration
25
32
  */
26
33
 
27
34
 
@@ -52,26 +59,36 @@ var rule = {
52
59
  return;
53
60
  }
54
61
 
62
+ if (node.value.type === 'Literal' && !isValidSpacingValue(node.value.value, fontSize)) {
63
+ context.report({
64
+ node: node,
65
+ messageId: 'noRawSpacingValues',
66
+ data: {
67
+ payload: "NaN:".concat(node.value.value)
68
+ }
69
+ });
70
+ return;
71
+ }
72
+
55
73
  var value = getValue(node.value, context);
56
74
 
57
- if (value) {
75
+ if (value && isValidSpacingValue(value, fontSize)) {
58
76
  var values = typeof value === 'number' || typeof value === 'string' ? [value] : value;
59
- values.forEach(function (value) {
77
+ values.forEach(function (val) {
60
78
  context.report({
61
79
  node: node,
62
80
  messageId: 'noRawSpacingValues',
63
81
  data: {
64
- payload: "".concat(node.key.name, ":").concat(emToPixels(value, fontSize))
82
+ payload: "".concat(node.key.name, ":").concat(emToPixels(val, fontSize))
65
83
  }
66
84
  });
67
85
  });
68
- return;
69
86
  } else {
70
87
  context.report({
71
88
  node: node,
72
89
  messageId: 'noRawSpacingValues',
73
90
  data: {
74
- payload: "".concat(node.key.name, ":NaN")
91
+ payload: "NaN:".concat(value)
75
92
  }
76
93
  });
77
94
  }
@@ -94,7 +111,9 @@ var rule = {
94
111
  * Adapted from ensure-design-token-usage
95
112
  */
96
113
 
97
- var cssProperties = combinedString.replace(/\n/g, '').split(/;|{|}/).map(function (el) {
114
+ var cssProperties = combinedString.split('\n').filter(function (line) {
115
+ return !line.trim().startsWith('@');
116
+ }).join('\n').replace(/\n/g, '').split(/;|{|}/).map(function (el) {
98
117
  return el.trim() || '';
99
118
  });
100
119
  cssProperties.map(function (style) {
@@ -103,14 +122,41 @@ var rule = {
103
122
  property = _style$split2[0],
104
123
  value = _style$split2[1];
105
124
 
125
+ property = convertHyphenatedNameToCamelCase(property);
126
+
106
127
  if (isSpacingProperty(property)) {
107
- context.report({
108
- node: node,
109
- messageId: 'noRawSpacingValues',
110
- data: {
111
- payload: "".concat(property, ":").concat(removePixelSuffix(value.trim()))
128
+ if (isValidSpacingValue(value)) {
129
+ var values = getValueFromShorthand(value);
130
+
131
+ var _iterator = _createForOfIteratorHelper(values),
132
+ _step;
133
+
134
+ try {
135
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
136
+ var val = _step.value;
137
+ // could be array of values e.g. padding: 8px 12px 3px
138
+ context.report({
139
+ node: node,
140
+ messageId: 'noRawSpacingValues',
141
+ data: {
142
+ payload: "".concat(property, ":").concat(val)
143
+ }
144
+ });
145
+ }
146
+ } catch (err) {
147
+ _iterator.e(err);
148
+ } finally {
149
+ _iterator.f();
112
150
  }
113
- });
151
+ } else {
152
+ context.report({
153
+ node: node,
154
+ messageId: 'noRawSpacingValues',
155
+ data: {
156
+ payload: "NaN:".concat(value)
157
+ }
158
+ });
159
+ }
114
160
  }
115
161
 
116
162
  return;
@@ -1,5 +1,5 @@
1
1
  import { isNodeOfType } from 'eslint-codemod-utils';
2
- var properties = ['padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'margin', 'gap', 'fontSize', 'lineHeight', 'width', 'height'];
2
+ var properties = ['padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'margin', 'gap', 'fontSize', 'lineHeight', 'width', 'height', 'rowGap', 'gridRowGap', 'columnGap', 'gridColumnGap'];
3
3
  export function findIdentifierInParentScope(_ref) {
4
4
  var scope = _ref.scope,
5
5
  identifierName = _ref.identifierName;
@@ -104,6 +104,10 @@ var getValueFromIdentifier = function getValueFromIdentifier(node, context) {
104
104
 
105
105
  var definition = variable.defs[0];
106
106
 
107
+ if (isNodeOfType(definition.node, 'ImportSpecifier') && isNodeOfType(definition.node.parent, 'ImportDeclaration') && definition.node.parent.source.value === '@atlassian/jira-common-legacy-do-not-add-anything-new/src/styles') {
108
+ return definition.node.imported.name === 'gridSize' ? 8 : null;
109
+ }
110
+
107
111
  if (!isNodeOfType(definition.node, 'VariableDeclarator')) {
108
112
  return null;
109
113
  }
@@ -127,7 +131,7 @@ var getValueFromUnaryExpression = function getValueFromUnaryExpression(node, con
127
131
  } // eslint-disable-next-line no-eval
128
132
 
129
133
 
130
- return eval("".concat(node.operator).concat(value));
134
+ return eval("".concat(node.operator, "(").concat(value, ")"));
131
135
  };
132
136
  /**
133
137
  * @example
@@ -178,9 +182,9 @@ export var emToPixels = function emToPixels(value, fontSize) {
178
182
 
179
183
  if (match && typeof fontSize === 'number') {
180
184
  return Number(match[1]) * fontSize;
185
+ } else {
186
+ return null;
181
187
  }
182
-
183
- return 'NaN';
184
188
  }
185
189
 
186
190
  return value;
@@ -195,4 +199,31 @@ export var removePixelSuffix = function removePixelSuffix(value) {
195
199
 
196
200
 
197
201
  return Number(isString ? value.replace('px', '') : value);
202
+ };
203
+ var invalidSpacingUnitRegex = /(%$)|(\d+rem$)|(^calc)|(vw$)|(vh$)/;
204
+ export var isValidSpacingValue = function isValidSpacingValue(value, fontSize) {
205
+ if (typeof value === 'string') {
206
+ if (invalidSpacingUnitRegex.test(value)) {
207
+ return false;
208
+ }
209
+ } else if (Array.isArray(value)) {
210
+ // could be array due to shorthand
211
+ for (var val in value) {
212
+ if (invalidSpacingUnitRegex.test(val)) {
213
+ return false;
214
+ }
215
+ }
216
+ }
217
+
218
+ if (emRegex.test(value) && typeof fontSize !== 'number') {
219
+ return false;
220
+ }
221
+
222
+ return true;
223
+ }; // convert line-height to lineHeight
224
+
225
+ export var convertHyphenatedNameToCamelCase = function convertHyphenatedNameToCamelCase(prop) {
226
+ return prop.replace(/-./g, function (m) {
227
+ return m[1].toUpperCase();
228
+ });
198
229
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
- "version": "4.10.0",
3
+ "version": "4.10.1",
4
4
  "sideEffects": false
5
5
  }
@@ -6,6 +6,8 @@ export declare function findIdentifierInParentScope({ scope, identifierName, }:
6
6
  }): Scope.Variable | null;
7
7
  export declare const isSpacingProperty: (prop: string) => boolean;
8
8
  export declare const getValueFromShorthand: (str: unknown) => any[];
9
- export declare const getValue: (node: EslintNode, context: Rule.RuleContext) => number | null | number[];
10
- export declare const emToPixels: <T extends unknown>(value: T, fontSize: number | null) => number | T | "NaN";
9
+ export declare const getValue: (node: EslintNode, context: Rule.RuleContext) => string | number | any[] | null | undefined;
10
+ export declare const emToPixels: <T extends unknown>(value: T, fontSize: number | null | undefined) => number | T | null;
11
11
  export declare const removePixelSuffix: (value: string | number) => string | number;
12
+ export declare const isValidSpacingValue: (value: string | number | boolean | RegExp | null | undefined | any[] | bigint, fontSize?: number | null | undefined) => boolean;
13
+ export declare const convertHyphenatedNameToCamelCase: (prop: string) => string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
3
  "description": "The essential plugin for use with the Atlassian Design System.",
4
- "version": "4.10.0",
4
+ "version": "4.10.1",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "publishConfig": {
7
7
  "registry": "https://registry.npmjs.org/"
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@atlaskit/ds-lib": "^2.1.0",
35
- "@atlaskit/theme": "^12.0.2",
35
+ "@atlaskit/theme": "^12.2.0",
36
36
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
37
37
  "@emotion/core": "^10.0.9",
38
38
  "@emotion/styled": "^11.0.0",