@atlaskit/eslint-plugin-design-system 13.37.0 → 13.38.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,22 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 13.38.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`414f1cb19fe79`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/414f1cb19fe79) -
8
+ Fix ensure-design-token-usage so Tag’s color prop is allowed when scope lookup fails by adding an
9
+ AST fallback for imports from @atlaskit/tag.
10
+
11
+ ## 13.38.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`93ff2e6c56a27`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/93ff2e6c56a27) -
16
+ The `ensure-design-token-usage` ESLint rule now allows `color` prop with string values (e.g.,
17
+ `"red"`, `"blue"`) on Tag components imported from `@atlaskit/tag` or its sub-entrypoints (e.g.,
18
+ `@atlaskit/tag/simple-tag`, `@atlaskit/tag/removable-tag`)
19
+
3
20
  ## 13.37.0
4
21
 
5
22
  ### Minor Changes
@@ -5,10 +5,103 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.lintTemplateIdentifierForColor = exports.lintObjectForColor = exports.lintJSXMemberForColor = exports.lintJSXLiteralForColor = exports.lintJSXIdentifierForColor = exports.getTokenSuggestion = exports.getElevationTokenExample = void 0;
7
7
  var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ var _contextCompat = require("@atlaskit/eslint-utils/context-compat");
8
9
  var _getIsException = require("../utils/get-is-exception");
9
10
  var _isColor = require("../utils/is-color");
10
11
  var _isElevation = require("../utils/is-elevation");
11
12
  var _isNode = require("../utils/is-node");
13
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
14
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
15
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
16
+ /**
17
+ * Check if the JSXAttribute is a 'color' prop on a Tag component imported from @atlaskit/tag
18
+ */
19
+ var isTagComponentColorProp = function isTagComponentColorProp(jsxAttributeNode, context) {
20
+ var _variable$defs;
21
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(jsxAttributeNode, 'JSXAttribute')) {
22
+ return false;
23
+ }
24
+
25
+ // Check if the attribute name is 'color'
26
+ var attributeName = typeof jsxAttributeNode.name.name === 'string' ? jsxAttributeNode.name.name : jsxAttributeNode.name.name.name;
27
+ if (attributeName !== 'color') {
28
+ return false;
29
+ }
30
+
31
+ // Find the JSXOpeningElement
32
+ var currentNode = jsxAttributeNode.parent;
33
+ while (currentNode && !(0, _eslintCodemodUtils.isNodeOfType)(currentNode, 'JSXOpeningElement')) {
34
+ currentNode = currentNode.parent;
35
+ }
36
+ if (!currentNode || !(0, _eslintCodemodUtils.isNodeOfType)(currentNode, 'JSXOpeningElement')) {
37
+ return false;
38
+ }
39
+
40
+ // Get the component name
41
+ var elementName = (0, _eslintCodemodUtils.isNodeOfType)(currentNode.name, 'JSXIdentifier') ? currentNode.name.name : null;
42
+ if (!elementName) {
43
+ return false;
44
+ }
45
+
46
+ // Check if the component is imported from @atlaskit/tag (scope-based resolution)
47
+ var scope = (0, _contextCompat.getScope)(context, jsxAttributeNode);
48
+ var variable = scope.variables.find(function (v) {
49
+ return v.name === elementName;
50
+ });
51
+ if (variable !== null && variable !== void 0 && (_variable$defs = variable.defs) !== null && _variable$defs !== void 0 && _variable$defs.length) {
52
+ var _iterator = _createForOfIteratorHelper(variable.defs),
53
+ _step;
54
+ try {
55
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
56
+ var def = _step.value;
57
+ if (def.type === 'ImportBinding' && def.parent && (0, _eslintCodemodUtils.isNodeOfType)(def.parent, 'ImportDeclaration')) {
58
+ var importSource = def.parent.source.value;
59
+ if (typeof importSource === 'string' && importSource.match(/^@atlaskit\/tag(\/|$)/)) {
60
+ return true;
61
+ }
62
+ }
63
+ }
64
+ } catch (err) {
65
+ _iterator.e(err);
66
+ } finally {
67
+ _iterator.f();
68
+ }
69
+ }
70
+
71
+ // Fallback: scan AST for ImportDeclaration (more reliable when scope differs e.g. in some monorepo/parser setups)
72
+ var sourceCode = (0, _contextCompat.getSourceCode)(context);
73
+ var ast = sourceCode.ast;
74
+ if (ast !== null && ast !== void 0 && ast.body) {
75
+ var _iterator2 = _createForOfIteratorHelper(ast.body),
76
+ _step2;
77
+ try {
78
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
79
+ var _node$source, _node$specifiers;
80
+ var node = _step2.value;
81
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'ImportDeclaration')) {
82
+ continue;
83
+ }
84
+ var source = (_node$source = node.source) === null || _node$source === void 0 ? void 0 : _node$source.value;
85
+ if (typeof source !== 'string' || !source.match(/^@atlaskit\/tag(\/|$)/)) {
86
+ continue;
87
+ }
88
+ var hasMatchingImport = (_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.some(function (s) {
89
+ var _s$local, _s$local2;
90
+ return s.type === 'ImportDefaultSpecifier' && ((_s$local = s.local) === null || _s$local === void 0 ? void 0 : _s$local.name) === elementName || s.type === 'ImportSpecifier' && ((_s$local2 = s.local) === null || _s$local2 === void 0 ? void 0 : _s$local2.name) === elementName;
91
+ });
92
+ if (hasMatchingImport) {
93
+ return true;
94
+ }
95
+ }
96
+ } catch (err) {
97
+ _iterator2.e(err);
98
+ } finally {
99
+ _iterator2.f();
100
+ }
101
+ }
102
+ return false;
103
+ };
104
+
12
105
  // TemplateLiteral > Identifier
13
106
  var lintTemplateIdentifierForColor = exports.lintTemplateIdentifierForColor = function lintTemplateIdentifierForColor(node, context, config) {
14
107
  if (node.type !== 'Identifier') {
@@ -154,6 +247,11 @@ var lintJSXLiteralForColor = exports.lintJSXLiteralForColor = function lintJSXLi
154
247
  return;
155
248
  }
156
249
 
250
+ // Bypass Tag component color prop from @atlaskit/tag
251
+ if (isTagComponentColorProp(parent, context)) {
252
+ return;
253
+ }
254
+
157
255
  // We only care about hex values
158
256
  if (typeof node.value !== 'string') {
159
257
  return;
@@ -214,7 +312,7 @@ var getTokenSuggestion = exports.getTokenSuggestion = function getTokenSuggestio
214
312
  shouldReturnSuggestion: !(0, _isNode.isDecendantOfGlobalToken)(node) && config.shouldEnforceFallbacks === false,
215
313
  desc: "Convert to token",
216
314
  fix: function fix(fixer) {
217
- return fixer.replaceText((0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'MemberExpression') ? node.parent : node, "token('')");
315
+ return fixer.replaceText((0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'MemberExpression') ? node.parent : node, (0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'JSXAttribute') ? "{token('')}" : "token('')");
218
316
  }
219
317
  }, {
220
318
  shouldReturnSuggestion: !(0, _isNode.isDecendantOfGlobalToken)(node) && config.shouldEnforceFallbacks === true,
@@ -1,8 +1,78 @@
1
1
  import { node as generate, isNodeOfType } from 'eslint-codemod-utils';
2
+ import { getScope, getSourceCode } from '@atlaskit/eslint-utils/context-compat';
2
3
  import { getIsException } from '../utils/get-is-exception';
3
4
  import { includesHardCodedColor, isHardCodedColor, isLegacyColor, isLegacyNamedColor } from '../utils/is-color';
4
5
  import { isLegacyElevation } from '../utils/is-elevation';
5
6
  import { isChildOfType, isDecendantOfGlobalToken, isDecendantOfPrimitive, isDecendantOfStyleBlock, isDecendantOfSvgElement } from '../utils/is-node';
7
+ /**
8
+ * Check if the JSXAttribute is a 'color' prop on a Tag component imported from @atlaskit/tag
9
+ */
10
+ const isTagComponentColorProp = (jsxAttributeNode, context) => {
11
+ var _variable$defs;
12
+ if (!isNodeOfType(jsxAttributeNode, 'JSXAttribute')) {
13
+ return false;
14
+ }
15
+
16
+ // Check if the attribute name is 'color'
17
+ const attributeName = typeof jsxAttributeNode.name.name === 'string' ? jsxAttributeNode.name.name : jsxAttributeNode.name.name.name;
18
+ if (attributeName !== 'color') {
19
+ return false;
20
+ }
21
+
22
+ // Find the JSXOpeningElement
23
+ let currentNode = jsxAttributeNode.parent;
24
+ while (currentNode && !isNodeOfType(currentNode, 'JSXOpeningElement')) {
25
+ currentNode = currentNode.parent;
26
+ }
27
+ if (!currentNode || !isNodeOfType(currentNode, 'JSXOpeningElement')) {
28
+ return false;
29
+ }
30
+
31
+ // Get the component name
32
+ const elementName = isNodeOfType(currentNode.name, 'JSXIdentifier') ? currentNode.name.name : null;
33
+ if (!elementName) {
34
+ return false;
35
+ }
36
+
37
+ // Check if the component is imported from @atlaskit/tag (scope-based resolution)
38
+ const scope = getScope(context, jsxAttributeNode);
39
+ const variable = scope.variables.find(v => v.name === elementName);
40
+ if (variable !== null && variable !== void 0 && (_variable$defs = variable.defs) !== null && _variable$defs !== void 0 && _variable$defs.length) {
41
+ for (const def of variable.defs) {
42
+ if (def.type === 'ImportBinding' && def.parent && isNodeOfType(def.parent, 'ImportDeclaration')) {
43
+ const importSource = def.parent.source.value;
44
+ if (typeof importSource === 'string' && importSource.match(/^@atlaskit\/tag(\/|$)/)) {
45
+ return true;
46
+ }
47
+ }
48
+ }
49
+ }
50
+
51
+ // Fallback: scan AST for ImportDeclaration (more reliable when scope differs e.g. in some monorepo/parser setups)
52
+ const sourceCode = getSourceCode(context);
53
+ const ast = sourceCode.ast;
54
+ if (ast !== null && ast !== void 0 && ast.body) {
55
+ for (const node of ast.body) {
56
+ var _node$source, _node$specifiers;
57
+ if (!isNodeOfType(node, 'ImportDeclaration')) {
58
+ continue;
59
+ }
60
+ const source = (_node$source = node.source) === null || _node$source === void 0 ? void 0 : _node$source.value;
61
+ if (typeof source !== 'string' || !source.match(/^@atlaskit\/tag(\/|$)/)) {
62
+ continue;
63
+ }
64
+ const hasMatchingImport = (_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.some(s => {
65
+ var _s$local, _s$local2;
66
+ return s.type === 'ImportDefaultSpecifier' && ((_s$local = s.local) === null || _s$local === void 0 ? void 0 : _s$local.name) === elementName || s.type === 'ImportSpecifier' && ((_s$local2 = s.local) === null || _s$local2 === void 0 ? void 0 : _s$local2.name) === elementName;
67
+ });
68
+ if (hasMatchingImport) {
69
+ return true;
70
+ }
71
+ }
72
+ }
73
+ return false;
74
+ };
75
+
6
76
  // TemplateLiteral > Identifier
7
77
  export const lintTemplateIdentifierForColor = (node, context, config) => {
8
78
  if (node.type !== 'Identifier') {
@@ -149,6 +219,11 @@ export const lintJSXLiteralForColor = (node, context, config) => {
149
219
  return;
150
220
  }
151
221
 
222
+ // Bypass Tag component color prop from @atlaskit/tag
223
+ if (isTagComponentColorProp(parent, context)) {
224
+ return;
225
+ }
226
+
152
227
  // We only care about hex values
153
228
  if (typeof node.value !== 'string') {
154
229
  return;
@@ -212,7 +287,7 @@ css({
212
287
  export const getTokenSuggestion = (node, reference, config) => [{
213
288
  shouldReturnSuggestion: !isDecendantOfGlobalToken(node) && config.shouldEnforceFallbacks === false,
214
289
  desc: `Convert to token`,
215
- fix: fixer => fixer.replaceText(isNodeOfType(node.parent, 'MemberExpression') ? node.parent : node, `token('')`)
290
+ fix: fixer => fixer.replaceText(isNodeOfType(node.parent, 'MemberExpression') ? node.parent : node, isNodeOfType(node.parent, 'JSXAttribute') ? `{token('')}` : `token('')`)
216
291
  }, {
217
292
  shouldReturnSuggestion: !isDecendantOfGlobalToken(node) && config.shouldEnforceFallbacks === true,
218
293
  desc: `Convert to token with fallback`,
@@ -1,8 +1,101 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
1
4
  import { node as generate, isNodeOfType } from 'eslint-codemod-utils';
5
+ import { getScope, getSourceCode } from '@atlaskit/eslint-utils/context-compat';
2
6
  import { getIsException } from '../utils/get-is-exception';
3
7
  import { includesHardCodedColor, isHardCodedColor, isLegacyColor, isLegacyNamedColor } from '../utils/is-color';
4
8
  import { isLegacyElevation } from '../utils/is-elevation';
5
9
  import { isChildOfType, isDecendantOfGlobalToken, isDecendantOfPrimitive, isDecendantOfStyleBlock, isDecendantOfSvgElement } from '../utils/is-node';
10
+ /**
11
+ * Check if the JSXAttribute is a 'color' prop on a Tag component imported from @atlaskit/tag
12
+ */
13
+ var isTagComponentColorProp = function isTagComponentColorProp(jsxAttributeNode, context) {
14
+ var _variable$defs;
15
+ if (!isNodeOfType(jsxAttributeNode, 'JSXAttribute')) {
16
+ return false;
17
+ }
18
+
19
+ // Check if the attribute name is 'color'
20
+ var attributeName = typeof jsxAttributeNode.name.name === 'string' ? jsxAttributeNode.name.name : jsxAttributeNode.name.name.name;
21
+ if (attributeName !== 'color') {
22
+ return false;
23
+ }
24
+
25
+ // Find the JSXOpeningElement
26
+ var currentNode = jsxAttributeNode.parent;
27
+ while (currentNode && !isNodeOfType(currentNode, 'JSXOpeningElement')) {
28
+ currentNode = currentNode.parent;
29
+ }
30
+ if (!currentNode || !isNodeOfType(currentNode, 'JSXOpeningElement')) {
31
+ return false;
32
+ }
33
+
34
+ // Get the component name
35
+ var elementName = isNodeOfType(currentNode.name, 'JSXIdentifier') ? currentNode.name.name : null;
36
+ if (!elementName) {
37
+ return false;
38
+ }
39
+
40
+ // Check if the component is imported from @atlaskit/tag (scope-based resolution)
41
+ var scope = getScope(context, jsxAttributeNode);
42
+ var variable = scope.variables.find(function (v) {
43
+ return v.name === elementName;
44
+ });
45
+ if (variable !== null && variable !== void 0 && (_variable$defs = variable.defs) !== null && _variable$defs !== void 0 && _variable$defs.length) {
46
+ var _iterator = _createForOfIteratorHelper(variable.defs),
47
+ _step;
48
+ try {
49
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
50
+ var def = _step.value;
51
+ if (def.type === 'ImportBinding' && def.parent && isNodeOfType(def.parent, 'ImportDeclaration')) {
52
+ var importSource = def.parent.source.value;
53
+ if (typeof importSource === 'string' && importSource.match(/^@atlaskit\/tag(\/|$)/)) {
54
+ return true;
55
+ }
56
+ }
57
+ }
58
+ } catch (err) {
59
+ _iterator.e(err);
60
+ } finally {
61
+ _iterator.f();
62
+ }
63
+ }
64
+
65
+ // Fallback: scan AST for ImportDeclaration (more reliable when scope differs e.g. in some monorepo/parser setups)
66
+ var sourceCode = getSourceCode(context);
67
+ var ast = sourceCode.ast;
68
+ if (ast !== null && ast !== void 0 && ast.body) {
69
+ var _iterator2 = _createForOfIteratorHelper(ast.body),
70
+ _step2;
71
+ try {
72
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
73
+ var _node$source, _node$specifiers;
74
+ var node = _step2.value;
75
+ if (!isNodeOfType(node, 'ImportDeclaration')) {
76
+ continue;
77
+ }
78
+ var source = (_node$source = node.source) === null || _node$source === void 0 ? void 0 : _node$source.value;
79
+ if (typeof source !== 'string' || !source.match(/^@atlaskit\/tag(\/|$)/)) {
80
+ continue;
81
+ }
82
+ var hasMatchingImport = (_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.some(function (s) {
83
+ var _s$local, _s$local2;
84
+ return s.type === 'ImportDefaultSpecifier' && ((_s$local = s.local) === null || _s$local === void 0 ? void 0 : _s$local.name) === elementName || s.type === 'ImportSpecifier' && ((_s$local2 = s.local) === null || _s$local2 === void 0 ? void 0 : _s$local2.name) === elementName;
85
+ });
86
+ if (hasMatchingImport) {
87
+ return true;
88
+ }
89
+ }
90
+ } catch (err) {
91
+ _iterator2.e(err);
92
+ } finally {
93
+ _iterator2.f();
94
+ }
95
+ }
96
+ return false;
97
+ };
98
+
6
99
  // TemplateLiteral > Identifier
7
100
  export var lintTemplateIdentifierForColor = function lintTemplateIdentifierForColor(node, context, config) {
8
101
  if (node.type !== 'Identifier') {
@@ -148,6 +241,11 @@ export var lintJSXLiteralForColor = function lintJSXLiteralForColor(node, contex
148
241
  return;
149
242
  }
150
243
 
244
+ // Bypass Tag component color prop from @atlaskit/tag
245
+ if (isTagComponentColorProp(parent, context)) {
246
+ return;
247
+ }
248
+
151
249
  // We only care about hex values
152
250
  if (typeof node.value !== 'string') {
153
251
  return;
@@ -208,7 +306,7 @@ export var getTokenSuggestion = function getTokenSuggestion(node, reference, con
208
306
  shouldReturnSuggestion: !isDecendantOfGlobalToken(node) && config.shouldEnforceFallbacks === false,
209
307
  desc: "Convert to token",
210
308
  fix: function fix(fixer) {
211
- return fixer.replaceText(isNodeOfType(node.parent, 'MemberExpression') ? node.parent : node, "token('')");
309
+ return fixer.replaceText(isNodeOfType(node.parent, 'MemberExpression') ? node.parent : node, isNodeOfType(node.parent, 'JSXAttribute') ? "{token('')}" : "token('')");
212
310
  }
213
311
  }, {
214
312
  shouldReturnSuggestion: !isDecendantOfGlobalToken(node) && config.shouldEnforceFallbacks === true,
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": "13.37.0",
4
+ "version": "13.38.1",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
7
7
  "publishConfig": {