@atlaskit/eslint-plugin-design-system 8.29.1 → 8.31.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 (81) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/configs/deprecated.json +0 -5
  4. package/constellation/index/usage.mdx +1 -1
  5. package/constellation/use-primitives-text/usage.mdx +21 -0
  6. package/dist/cjs/ast-nodes/jsx-element.js +33 -2
  7. package/dist/cjs/presets/all.codegen.js +2 -2
  8. package/dist/cjs/presets/recommended.codegen.js +1 -2
  9. package/dist/cjs/rules/index.codegen.js +3 -3
  10. package/dist/cjs/rules/use-primitives/transformers/emotion-css/index.js +1 -2
  11. package/dist/cjs/rules/use-primitives-text/config/index.js +15 -0
  12. package/dist/cjs/rules/use-primitives-text/index.js +57 -0
  13. package/dist/cjs/rules/use-primitives-text/transformers/common.js +43 -0
  14. package/dist/cjs/rules/use-primitives-text/transformers/emphasis-elements.js +82 -0
  15. package/dist/cjs/rules/use-primitives-text/transformers/index.js +33 -0
  16. package/dist/cjs/rules/use-primitives-text/transformers/paragraph-elements.js +196 -0
  17. package/dist/cjs/rules/use-primitives-text/transformers/span-elements.js +87 -0
  18. package/dist/cjs/rules/use-primitives-text/transformers/strong-elements.js +82 -0
  19. package/dist/configs/deprecated.json +0 -5
  20. package/dist/es2019/ast-nodes/jsx-element.js +33 -2
  21. package/dist/es2019/presets/all.codegen.js +2 -2
  22. package/dist/es2019/presets/recommended.codegen.js +1 -2
  23. package/dist/es2019/rules/index.codegen.js +3 -3
  24. package/dist/es2019/rules/use-primitives/transformers/emotion-css/index.js +1 -2
  25. package/dist/es2019/rules/use-primitives-text/config/index.js +9 -0
  26. package/dist/es2019/rules/use-primitives-text/index.js +51 -0
  27. package/dist/es2019/rules/use-primitives-text/transformers/common.js +33 -0
  28. package/dist/es2019/rules/use-primitives-text/transformers/emphasis-elements.js +72 -0
  29. package/dist/es2019/rules/use-primitives-text/transformers/index.js +4 -0
  30. package/dist/es2019/rules/use-primitives-text/transformers/paragraph-elements.js +187 -0
  31. package/dist/es2019/rules/use-primitives-text/transformers/span-elements.js +77 -0
  32. package/dist/es2019/rules/use-primitives-text/transformers/strong-elements.js +72 -0
  33. package/dist/esm/ast-nodes/jsx-element.js +33 -2
  34. package/dist/esm/presets/all.codegen.js +2 -2
  35. package/dist/esm/presets/recommended.codegen.js +1 -2
  36. package/dist/esm/rules/index.codegen.js +3 -3
  37. package/dist/esm/rules/use-primitives/transformers/emotion-css/index.js +1 -2
  38. package/dist/esm/rules/use-primitives-text/config/index.js +9 -0
  39. package/dist/esm/rules/use-primitives-text/index.js +51 -0
  40. package/dist/esm/rules/use-primitives-text/transformers/common.js +33 -0
  41. package/dist/esm/rules/use-primitives-text/transformers/emphasis-elements.js +72 -0
  42. package/dist/esm/rules/use-primitives-text/transformers/index.js +4 -0
  43. package/dist/esm/rules/use-primitives-text/transformers/paragraph-elements.js +186 -0
  44. package/dist/esm/rules/use-primitives-text/transformers/span-elements.js +77 -0
  45. package/dist/esm/rules/use-primitives-text/transformers/strong-elements.js +72 -0
  46. package/dist/types/ast-nodes/jsx-element.d.ts +5 -2
  47. package/dist/types/index.codegen.d.ts +1 -2
  48. package/dist/types/presets/all.codegen.d.ts +2 -2
  49. package/dist/types/presets/recommended.codegen.d.ts +1 -2
  50. package/dist/types/rules/index.codegen.d.ts +1 -1
  51. package/dist/types/rules/use-primitives-text/config/index.d.ts +6 -0
  52. package/dist/types/rules/{local-cx-xcss → use-primitives-text}/index.d.ts +1 -1
  53. package/dist/types/rules/use-primitives-text/transformers/common.d.ts +5 -0
  54. package/dist/types/rules/use-primitives-text/transformers/emphasis-elements.d.ts +16 -0
  55. package/dist/types/rules/use-primitives-text/transformers/index.d.ts +4 -0
  56. package/dist/types/rules/use-primitives-text/transformers/paragraph-elements.d.ts +32 -0
  57. package/dist/types/rules/use-primitives-text/transformers/span-elements.d.ts +16 -0
  58. package/dist/types/rules/use-primitives-text/transformers/strong-elements.d.ts +16 -0
  59. package/dist/types-ts4.5/ast-nodes/jsx-element.d.ts +5 -2
  60. package/dist/types-ts4.5/index.codegen.d.ts +1 -2
  61. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -2
  62. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +1 -2
  63. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -1
  64. package/dist/types-ts4.5/rules/use-primitives-text/config/index.d.ts +6 -0
  65. package/dist/types-ts4.5/rules/{local-cx-xcss → use-primitives-text}/index.d.ts +1 -1
  66. package/dist/types-ts4.5/rules/use-primitives-text/transformers/common.d.ts +5 -0
  67. package/dist/types-ts4.5/rules/use-primitives-text/transformers/emphasis-elements.d.ts +16 -0
  68. package/dist/types-ts4.5/rules/use-primitives-text/transformers/index.d.ts +4 -0
  69. package/dist/types-ts4.5/rules/use-primitives-text/transformers/paragraph-elements.d.ts +32 -0
  70. package/dist/types-ts4.5/rules/use-primitives-text/transformers/span-elements.d.ts +16 -0
  71. package/dist/types-ts4.5/rules/use-primitives-text/transformers/strong-elements.d.ts +16 -0
  72. package/package.json +1 -1
  73. package/constellation/local-cx-xcss/usage.mdx +0 -37
  74. package/dist/cjs/rules/local-cx-xcss/index.js +0 -51
  75. package/dist/cjs/rules/use-primitives/transformers/emotion-css/contains-only-supported-attrs.js +0 -27
  76. package/dist/es2019/rules/local-cx-xcss/index.js +0 -45
  77. package/dist/es2019/rules/use-primitives/transformers/emotion-css/contains-only-supported-attrs.js +0 -19
  78. package/dist/esm/rules/local-cx-xcss/index.js +0 -45
  79. package/dist/esm/rules/use-primitives/transformers/emotion-css/contains-only-supported-attrs.js +0 -19
  80. package/dist/types/rules/use-primitives/transformers/emotion-css/contains-only-supported-attrs.d.ts +0 -7
  81. package/dist/types-ts4.5/rules/use-primitives/transformers/emotion-css/contains-only-supported-attrs.d.ts +0 -7
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.ParagraphElements = void 0;
9
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
11
+ var ast = _interopRequireWildcard(require("../../../ast-nodes"));
12
+ var _upsertImportDeclaration = require("../../use-primitives/transformers/emotion-css/upsert-import-declaration");
13
+ var _common = require("./common");
14
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
16
+ /* eslint-disable @repo/internal/react/require-jsdoc */
17
+
18
+ var ParagraphElements = exports.ParagraphElements = {
19
+ lint: function lint(node, _ref) {
20
+ var context = _ref.context,
21
+ config = _ref.config;
22
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
23
+ return;
24
+ }
25
+
26
+ // Check whether all criteria needed to make a transformation are met
27
+ var _ParagraphElements$_c = ParagraphElements._check(node, {
28
+ context: context,
29
+ config: config
30
+ }),
31
+ success = _ParagraphElements$_c.success,
32
+ refs = _ParagraphElements$_c.refs;
33
+ if (!success) {
34
+ return;
35
+ }
36
+ if (refs.siblings.length > 1) {
37
+ var _refs$siblings$0$loc, _refs$siblings$loc;
38
+ /**
39
+ * Highlighting from first opening element to last closing element
40
+ * to indicate fix will change all p elements and wrap them in a Stack,
41
+ * falls back to first opening element.
42
+ */
43
+ var startLoc = (_refs$siblings$0$loc = refs.siblings[0].loc) === null || _refs$siblings$0$loc === void 0 ? void 0 : _refs$siblings$0$loc.start;
44
+ var endLoc = (_refs$siblings$loc = refs.siblings[refs.siblings.length - 1].loc) === null || _refs$siblings$loc === void 0 ? void 0 : _refs$siblings$loc.end;
45
+ context.report({
46
+ loc: startLoc && endLoc && {
47
+ start: startLoc,
48
+ end: endLoc
49
+ },
50
+ node: node.openingElement,
51
+ messageId: 'preferPrimitivesStackedText',
52
+ suggest: [{
53
+ desc: 'Convert to Text and Stack',
54
+ fix: ParagraphElements._fixMultiple(node, {
55
+ context: context,
56
+ refs: refs
57
+ })
58
+ }]
59
+ });
60
+ } else {
61
+ context.report({
62
+ node: node,
63
+ messageId: 'preferPrimitivesText',
64
+ suggest: [{
65
+ desc: 'Convert to Text',
66
+ fix: ParagraphElements._fixSingle(node, {
67
+ context: context
68
+ })
69
+ }]
70
+ });
71
+ }
72
+ },
73
+ _check: function _check(node, _ref2) {
74
+ var context = _ref2.context,
75
+ config = _ref2.config;
76
+ if (!config.patterns.includes('paragraph-elements')) {
77
+ return {
78
+ success: false,
79
+ refs: {
80
+ siblings: []
81
+ }
82
+ };
83
+ }
84
+ var elementName = ast.JSXElement.getName(node);
85
+ if (elementName !== 'p') {
86
+ return {
87
+ success: false,
88
+ refs: {
89
+ siblings: []
90
+ }
91
+ };
92
+ }
93
+
94
+ // All siblings have to be paragraph elements with no unallowed props
95
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'JSXElement')) {
96
+ return {
97
+ success: false,
98
+ refs: {
99
+ siblings: []
100
+ }
101
+ };
102
+ }
103
+ var siblings = ast.JSXElement.getChildren(node.parent);
104
+ if (siblings.length > 1) {
105
+ var _siblings$0$range, _node$range, _siblings$0$range2, _node$range2;
106
+ // Only report for the first p element by comparing node location
107
+ if (((_siblings$0$range = siblings[0].range) === null || _siblings$0$range === void 0 ? void 0 : _siblings$0$range[0]) !== ((_node$range = node.range) === null || _node$range === void 0 ? void 0 : _node$range[0]) || ((_siblings$0$range2 = siblings[0].range) === null || _siblings$0$range2 === void 0 ? void 0 : _siblings$0$range2[1]) !== ((_node$range2 = node.range) === null || _node$range2 === void 0 ? void 0 : _node$range2[1])) {
108
+ return {
109
+ success: false,
110
+ refs: {
111
+ siblings: siblings
112
+ }
113
+ };
114
+ }
115
+ // Only report when every sibling is a p element
116
+ var siblingsMatch = siblings.every(function (child) {
117
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(child, 'JSXElement')) {
118
+ return false;
119
+ }
120
+ if (ast.JSXElement.getName(child) !== 'p') {
121
+ return false;
122
+ }
123
+ return ast.JSXElement.hasAllowedAttrsOnly(child, _common.allowedAttrs);
124
+ });
125
+ if (!siblingsMatch) {
126
+ return {
127
+ success: false,
128
+ refs: {
129
+ siblings: siblings
130
+ }
131
+ };
132
+ }
133
+ }
134
+ var importDeclaration = ast.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/primitives');
135
+
136
+ // If there is more than one `@atlaskit/primitives` import, then it becomes difficult to determine which import to transform
137
+ if (importDeclaration.length > 1) {
138
+ return {
139
+ success: false,
140
+ refs: {
141
+ siblings: siblings
142
+ }
143
+ };
144
+ }
145
+ return {
146
+ success: true,
147
+ refs: {
148
+ siblings: siblings
149
+ }
150
+ };
151
+ },
152
+ _fixSingle: function _fixSingle(node, _ref3) {
153
+ var context = _ref3.context;
154
+ return function (fixer) {
155
+ var importFix = (0, _upsertImportDeclaration.upsertImportDeclaration)({
156
+ module: '@atlaskit/primitives',
157
+ specifiers: ['Text']
158
+ }, context, fixer);
159
+ var elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
160
+ var testAttributeFix = (0, _common.updateTestIdAttributeFix)(node, fixer);
161
+ return [importFix].concat((0, _toConsumableArray2.default)(elementNameFixes), [testAttributeFix]).filter(function (fix) {
162
+ return Boolean(fix);
163
+ }); // Some of the transformers can return arrays with undefined, so filter them out
164
+ };
165
+ },
166
+ _fixMultiple: function _fixMultiple(node, _ref4) {
167
+ var context = _ref4.context,
168
+ refs = _ref4.refs;
169
+ return function (fixer) {
170
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.parent, 'JSXElement') || !node.parent.closingElement) {
171
+ return [];
172
+ }
173
+ var importFix = (0, _upsertImportDeclaration.upsertImportDeclaration)({
174
+ module: '@atlaskit/primitives',
175
+ specifiers: ['Text', 'Stack']
176
+ }, context, fixer);
177
+
178
+ // Update all siblings elements and their attributes
179
+ var siblingFixes = refs.siblings.map(function (sibling) {
180
+ if ((0, _eslintCodemodUtils.isNodeOfType)(sibling, 'JSXElement')) {
181
+ var elementNameFixes = ast.JSXElement.updateName(sibling, 'Text', fixer);
182
+ var testAttributeFix = (0, _common.updateTestIdAttributeFix)(sibling, fixer);
183
+ return [].concat((0, _toConsumableArray2.default)(elementNameFixes), [testAttributeFix]);
184
+ }
185
+ return undefined;
186
+ }).flat();
187
+
188
+ // Wrap in <Stack /> when more than 1 sibling
189
+ var wrapperOpenElementFix = fixer.insertTextAfter(node.parent.openingElement, "<Stack space='space.150'>");
190
+ var wrapperCloseElementFix = fixer.insertTextBefore(node.parent.closingElement, '</Stack>');
191
+ return [importFix].concat((0, _toConsumableArray2.default)(siblingFixes), [wrapperOpenElementFix, wrapperCloseElementFix]).filter(function (fix) {
192
+ return Boolean(fix);
193
+ }); // Some of the transformers can return arrays with undefined, so filter them out
194
+ };
195
+ }
196
+ };
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.SpanElements = void 0;
9
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
11
+ var ast = _interopRequireWildcard(require("../../../ast-nodes"));
12
+ var _upsertImportDeclaration = require("../../use-primitives/transformers/emotion-css/upsert-import-declaration");
13
+ var _common = require("./common");
14
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
16
+ /* eslint-disable @repo/internal/react/require-jsdoc */
17
+
18
+ var SpanElements = exports.SpanElements = {
19
+ lint: function lint(node, _ref) {
20
+ var context = _ref.context,
21
+ config = _ref.config;
22
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
23
+ return;
24
+ }
25
+
26
+ // Check whether all criteria needed to make a transformation are met
27
+ if (!SpanElements._check(node, {
28
+ context: context,
29
+ config: config
30
+ })) {
31
+ return;
32
+ }
33
+ context.report({
34
+ node: node.openingElement,
35
+ messageId: 'preferPrimitivesText',
36
+ suggest: [{
37
+ desc: "Convert to Text",
38
+ fix: SpanElements._fix(node, {
39
+ context: context
40
+ })
41
+ }]
42
+ });
43
+ },
44
+ _check: function _check(node, _ref2) {
45
+ var context = _ref2.context,
46
+ config = _ref2.config;
47
+ if (!config.patterns.includes('span-elements')) {
48
+ return false;
49
+ }
50
+ var elementName = ast.JSXElement.getName(node);
51
+ if (elementName !== 'span') {
52
+ return false;
53
+ }
54
+
55
+ // Element has no unallowed props
56
+ if (!ast.JSXElement.hasAllowedAttrsOnly(node, _common.allowedAttrs)) {
57
+ return false;
58
+ }
59
+
60
+ // Only allow elements with strings as children
61
+ if (!(0, _common.hasTextChildrenOnly)(node)) {
62
+ return false;
63
+ }
64
+ var importDeclaration = ast.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/primitives');
65
+
66
+ // If there is more than one `@atlaskit/primitives` import, then it becomes difficult to determine which import to transform
67
+ if (importDeclaration.length > 1) {
68
+ return false;
69
+ }
70
+ return true;
71
+ },
72
+ _fix: function _fix(node, _ref3) {
73
+ var context = _ref3.context;
74
+ return function (fixer) {
75
+ var importFix = (0, _upsertImportDeclaration.upsertImportDeclaration)({
76
+ module: '@atlaskit/primitives',
77
+ specifiers: ['Text']
78
+ }, context, fixer);
79
+ var elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
80
+ var variantAttributeFix = ast.JSXElement.addAttribute(node, 'variant', 'ui', fixer);
81
+ var testAttributeFix = (0, _common.updateTestIdAttributeFix)(node, fixer);
82
+ return [importFix].concat((0, _toConsumableArray2.default)(elementNameFixes), [variantAttributeFix, testAttributeFix]).filter(function (fix) {
83
+ return Boolean(fix);
84
+ }); // Some of the transformers can return arrays with undefined, so filter them out
85
+ };
86
+ }
87
+ };
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.StrongElements = void 0;
9
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
11
+ var ast = _interopRequireWildcard(require("../../../ast-nodes"));
12
+ var _upsertImportDeclaration = require("../../use-primitives/transformers/emotion-css/upsert-import-declaration");
13
+ var _common = require("./common");
14
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
16
+ /* eslint-disable @repo/internal/react/require-jsdoc */
17
+
18
+ var StrongElements = exports.StrongElements = {
19
+ lint: function lint(node, _ref) {
20
+ var context = _ref.context,
21
+ config = _ref.config;
22
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
23
+ return;
24
+ }
25
+
26
+ // Check whether all criteria needed to make a transformation are met
27
+ if (!StrongElements._check(node, {
28
+ context: context,
29
+ config: config
30
+ })) {
31
+ return;
32
+ }
33
+ context.report({
34
+ node: node.openingElement,
35
+ messageId: 'preferPrimitivesText',
36
+ suggest: [{
37
+ desc: "Convert to Text",
38
+ fix: StrongElements._fix(node, {
39
+ context: context
40
+ })
41
+ }]
42
+ });
43
+ },
44
+ _check: function _check(node, _ref2) {
45
+ var context = _ref2.context,
46
+ config = _ref2.config;
47
+ if (!config.patterns.includes('strong-elements')) {
48
+ return false;
49
+ }
50
+ var elementName = ast.JSXElement.getName(node);
51
+ if (elementName !== 'strong') {
52
+ return false;
53
+ }
54
+
55
+ // Element has no unallowed props
56
+ if (!ast.JSXElement.hasAllowedAttrsOnly(node, _common.allowedAttrs)) {
57
+ return false;
58
+ }
59
+
60
+ // If there is more than one `@atlaskit/primitives` import, then it becomes difficult to determine which import to transform
61
+ var importDeclaration = ast.Root.findImportsByModule(context.getSourceCode().ast.body, '@atlaskit/primitives');
62
+ if (importDeclaration.length > 1) {
63
+ return false;
64
+ }
65
+ return true;
66
+ },
67
+ _fix: function _fix(node, _ref3) {
68
+ var context = _ref3.context;
69
+ return function (fixer) {
70
+ var importFix = (0, _upsertImportDeclaration.upsertImportDeclaration)({
71
+ module: '@atlaskit/primitives',
72
+ specifiers: ['Text']
73
+ }, context, fixer);
74
+ var elementNameFixes = ast.JSXElement.updateName(node, 'Text', fixer);
75
+ var asAttributeFix = ast.JSXElement.addAttribute(node, 'as', 'strong', fixer);
76
+ var testAttributeFix = (0, _common.updateTestIdAttributeFix)(node, fixer);
77
+ return [importFix].concat((0, _toConsumableArray2.default)(elementNameFixes), [asAttributeFix, testAttributeFix]).filter(function (fix) {
78
+ return Boolean(fix);
79
+ }); // Some of the transformers can return arrays with undefined, so filter them out
80
+ };
81
+ }
82
+ };
@@ -43,11 +43,6 @@
43
43
  {
44
44
  "moduleSpecifier": "@atlaskit/logo"
45
45
  }
46
- ],
47
- "enableRemoteAdminLinks": [
48
- {
49
- "moduleSpecifier": "@atlassian/switcher"
50
- }
51
46
  ]
52
47
  },
53
48
  "imports": {
@@ -1,4 +1,5 @@
1
1
  import { isNodeOfType, jsxIdentifier } from 'eslint-codemod-utils';
2
+ import { JSXAttribute as HelperJSXAttribute } from './jsx-attribute';
2
3
  export const JSXElementHelper = {
3
4
  /**
4
5
  * Names of JSXElements can be any of:
@@ -6,8 +7,8 @@ export const JSXElementHelper = {
6
7
  * `<MyComponents.Component></MyComponents.Component>` - `MyComponents` is a namespace (JSXNamespacedName)
7
8
  * `<MyComponents.Component></MyComponents.Component>` - `MyComponents` is an object (JSXMemberExpression)
8
9
  *
9
- * Getting the name of a JSXMemberExpression is difficult, because object can contain objects, which is recursively defined in the AST.
10
- * e.g. getting the name of `<MyComponents.PresentationLayer.LeftSideBar.Header />` would require `getName` to recursively resolve all parts of the name.
10
+ * getting the name of a JSXMemberExpression is difficult, because object can contain objects, which is recursively defined in the AST.
11
+ * e.g. Getting the name of `<MyComponents.PresentationLayer.LeftSideBar.Header />` would require `getName` to recursively resolve all parts of the name.
11
12
  * `getName` does not currently have this functionality. Add it if you need it.
12
13
  */
13
14
  getName(node) {
@@ -45,6 +46,36 @@ export const JSXElementHelper = {
45
46
  return node.openingElement.attributes.some(attr => {
46
47
  return isNodeOfType(attr, 'JSXSpreadAttribute');
47
48
  });
49
+ },
50
+ addAttribute(node, name, value, fixer) {
51
+ const attributeString = ` ${name}='${value}'`;
52
+ const isSelfClosing = JSXElementHelper.isSelfClosing(node);
53
+ const start = node.openingElement.range ? node.openingElement.range[0] : 0;
54
+ const end = node.openingElement.range ? node.openingElement.range[1] - (isSelfClosing ? 3 : 1) : 0;
55
+ const range = [start, end];
56
+ const fix = fixer.insertTextAfterRange(range, attributeString);
57
+ return fix;
58
+ },
59
+ getChildren(node) {
60
+ // Filter out text children with whitespace characters only as JSX removes whitespace used for intendation
61
+ const filteredChildren = node.children.filter(child => {
62
+ if (isNodeOfType(child, 'JSXText')) {
63
+ const whiteSpaceChars = new RegExp('\\s', 'g');
64
+ return !whiteSpaceChars.test(child.value);
65
+ }
66
+ return true;
67
+ });
68
+ return filteredChildren;
69
+ },
70
+ hasAllowedAttrsOnly(node, allowedProps) {
71
+ const attrs = JSXElementHelper.getAttributes(node);
72
+ return attrs.every(attr => {
73
+ if (!isNodeOfType(attr, 'JSXAttribute')) {
74
+ return false;
75
+ }
76
+ const name = HelperJSXAttribute.getName(attr);
77
+ return allowedProps.includes(name);
78
+ });
48
79
  }
49
80
  };
50
81
  export { JSXElementHelper as JSXElement };
@@ -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::5647ce9c10ba880cffece66b5924fd6e>>
3
+ * @codegen <<SignedSource::aa64b4343b8763cfa5aa66230faea408>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -10,7 +10,6 @@ export default {
10
10
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
11
11
  '@atlaskit/design-system/ensure-design-token-usage/preview': 'warn',
12
12
  '@atlaskit/design-system/icon-label': 'warn',
13
- '@atlaskit/design-system/local-cx-xcss': 'error',
14
13
  '@atlaskit/design-system/no-banned-imports': 'error',
15
14
  '@atlaskit/design-system/no-css-tagged-template-expression': 'error',
16
15
  '@atlaskit/design-system/no-deprecated-apis': 'error',
@@ -34,6 +33,7 @@ export default {
34
33
  '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
35
34
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
36
35
  '@atlaskit/design-system/use-primitives': 'warn',
36
+ '@atlaskit/design-system/use-primitives-text': 'warn',
37
37
  '@atlaskit/design-system/use-visually-hidden': 'error'
38
38
  }
39
39
  };
@@ -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::577269c832952ce359cde6a50f26f4e0>>
3
+ * @codegen <<SignedSource::aebc778f0b10032cbb2941b55189d766>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  export default {
@@ -9,7 +9,6 @@ export default {
9
9
  '@atlaskit/design-system/consistent-css-prop-usage': 'error',
10
10
  '@atlaskit/design-system/ensure-design-token-usage': 'error',
11
11
  '@atlaskit/design-system/icon-label': 'warn',
12
- '@atlaskit/design-system/local-cx-xcss': 'error',
13
12
  '@atlaskit/design-system/no-banned-imports': 'error',
14
13
  '@atlaskit/design-system/no-deprecated-apis': 'error',
15
14
  '@atlaskit/design-system/no-deprecated-design-token-usage': 'warn',
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
3
- * @codegen <<SignedSource::0a2813f0b87e94d23e1f6fc388539c70>>
3
+ * @codegen <<SignedSource::7d840a5791dae4a9dfc4dda8ec00dcf9>>
4
4
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
5
5
  */
6
6
  import consistentCssPropUsage from './consistent-css-prop-usage';
7
7
  import ensureDesignTokenUsage from './ensure-design-token-usage';
8
8
  import ensureDesignTokenUsagePreview from './ensure-design-token-usage-preview';
9
9
  import iconLabel from './icon-label';
10
- import localCxXcss from './local-cx-xcss';
11
10
  import noBannedImports from './no-banned-imports';
12
11
  import noCssTaggedTemplateExpression from './no-css-tagged-template-expression';
13
12
  import noDeprecatedApis from './no-deprecated-apis';
@@ -31,13 +30,13 @@ import useDrawerLabel from './use-drawer-label';
31
30
  import useHeadingLevelInSpotlightCard from './use-heading-level-in-spotlight-card';
32
31
  import useHrefInLinkItem from './use-href-in-link-item';
33
32
  import usePrimitives from './use-primitives';
33
+ import usePrimitivesText from './use-primitives-text';
34
34
  import useVisuallyHidden from './use-visually-hidden';
35
35
  export default {
36
36
  'consistent-css-prop-usage': consistentCssPropUsage,
37
37
  'ensure-design-token-usage': ensureDesignTokenUsage,
38
38
  'ensure-design-token-usage/preview': ensureDesignTokenUsagePreview,
39
39
  'icon-label': iconLabel,
40
- 'local-cx-xcss': localCxXcss,
41
40
  'no-banned-imports': noBannedImports,
42
41
  'no-css-tagged-template-expression': noCssTaggedTemplateExpression,
43
42
  'no-deprecated-apis': noDeprecatedApis,
@@ -61,5 +60,6 @@ export default {
61
60
  'use-heading-level-in-spotlight-card': useHeadingLevelInSpotlightCard,
62
61
  'use-href-in-link-item': useHrefInLinkItem,
63
62
  'use-primitives': usePrimitives,
63
+ 'use-primitives-text': usePrimitivesText,
64
64
  'use-visually-hidden': useVisuallyHidden
65
65
  };
@@ -4,7 +4,6 @@ import { getIdentifierInParentScope, isNodeOfType } from 'eslint-codemod-utils';
4
4
  import * as ast from '../../../../ast-nodes';
5
5
  import { getVariableDefinitionValue, getVariableUsagesCount, isValidCssPropertiesToTransform } from '../../utils';
6
6
  import { cssToXcssTransformer } from '../css-to-xcss';
7
- import { containsOnlySupportedAttrs } from './contains-only-supported-attrs';
8
7
  import * as supported from './supported';
9
8
  import { upsertImportDeclaration } from './upsert-import-declaration';
10
9
  export const EmotionCSS = {
@@ -56,7 +55,7 @@ export const EmotionCSS = {
56
55
  }
57
56
 
58
57
  // Ignore elements that contain dangerous attributes like `id`.
59
- if (!containsOnlySupportedAttrs(node)) {
58
+ if (!ast.JSXElement.hasAllowedAttrsOnly(node, supported.attributes)) {
60
59
  return false;
61
60
  }
62
61
 
@@ -0,0 +1,9 @@
1
+ const defaults = {
2
+ patterns: ['paragraph-elements', 'span-elements', 'strong-elements', 'emphasis-elements']
3
+ };
4
+ export const getConfig = overrides => {
5
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
6
+ // start with an empty object, then merge in the defaults, then merge in overrides.
7
+ // The empty object is returned, as well as modified in place
8
+ return Object.assign({}, defaults, overrides);
9
+ };
@@ -0,0 +1,51 @@
1
+ import { createLintRule } from '../utils/create-rule';
2
+ import { getConfig } from './config';
3
+ import { EmphasisElements, ParagraphElements, SpanElements, StrongElements } from './transformers';
4
+ const textDocsUrl = 'https://atlassian.design/components/primitives/text';
5
+ const rule = createLintRule({
6
+ meta: {
7
+ name: 'use-primitives-text',
8
+ type: 'suggestion',
9
+ fixable: 'code',
10
+ hasSuggestions: true,
11
+ docs: {
12
+ description: 'Encourage the usage of text components.',
13
+ recommended: false,
14
+ severity: 'warn'
15
+ },
16
+ messages: {
17
+ preferPrimitivesText: `This element can be replaced with a "Text" primitive. See ${textDocsUrl} for additional guidance.`,
18
+ preferPrimitivesStackedText: `These paragraphs can be replaced with a "Text" and "Stack" primitives. See ${textDocsUrl} for additional guidance.`
19
+ }
20
+ },
21
+ create(context) {
22
+ const config = getConfig(context.options[0]);
23
+ return {
24
+ 'JSXElement[openingElement.name.name=span]': node => {
25
+ return SpanElements.lint(node, {
26
+ context,
27
+ config
28
+ });
29
+ },
30
+ 'JSXElement[openingElement.name.name=p]': node => {
31
+ return ParagraphElements.lint(node, {
32
+ context,
33
+ config
34
+ });
35
+ },
36
+ 'JSXElement[openingElement.name.name=strong]': node => {
37
+ return StrongElements.lint(node, {
38
+ context,
39
+ config
40
+ });
41
+ },
42
+ 'JSXElement[openingElement.name.name=em]': node => {
43
+ return EmphasisElements.lint(node, {
44
+ context,
45
+ config
46
+ });
47
+ }
48
+ };
49
+ }
50
+ });
51
+ export default rule;
@@ -0,0 +1,33 @@
1
+ import { isNodeOfType } from 'eslint-codemod-utils';
2
+ import * as ast from '../../../ast-nodes';
3
+
4
+ // Rename data-testid prop to testId if present
5
+ export function updateTestIdAttributeFix(node, fixer) {
6
+ const testIdAttr = ast.JSXElement.getAttributeByName(node, 'data-testid');
7
+ if (testIdAttr) {
8
+ return ast.JSXAttribute.updateName(testIdAttr, 'testId', fixer);
9
+ }
10
+ }
11
+ export const allowedAttrs = ['id', 'data-testid', 'key'];
12
+
13
+ // Only allow elements with strings as children
14
+ // The use of `FormattedMessage` component and `formatMessage` are allowed as these are used for i18n
15
+ export function hasTextChildrenOnly(node) {
16
+ var _node$children;
17
+ return (_node$children = node.children) === null || _node$children === void 0 ? void 0 : _node$children.every(child => {
18
+ if (isNodeOfType(child, 'JSXText')) {
19
+ return true;
20
+ }
21
+
22
+ // JSX child element <span><FormattedMessage /></span>
23
+ if (isNodeOfType(child, 'JSXElement') && ast.JSXElement.getName(child) === 'FormattedMessage') {
24
+ return true;
25
+ }
26
+
27
+ // JSX expression <span>{formatMessage(...)}</span>
28
+ if (isNodeOfType(child, 'JSXExpressionContainer') && isNodeOfType(child.expression, 'CallExpression')) {
29
+ return ast.FunctionCall.getName(child.expression) === 'formatMessage';
30
+ }
31
+ return false;
32
+ });
33
+ }