@atlaskit/eslint-plugin-design-system 8.17.0 → 8.18.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -0
  3. package/constellation/index/usage.mdx +22 -0
  4. package/dist/cjs/presets/all.codegen.js +2 -1
  5. package/dist/cjs/presets/recommended.codegen.js +2 -1
  6. package/dist/cjs/rules/index.codegen.js +3 -1
  7. package/dist/cjs/rules/use-heading-level-in-spotlight-card/index.js +63 -0
  8. package/dist/cjs/rules/use-href-in-link-item/index.js +2 -1
  9. package/dist/cjs/rules/use-href-in-link-item/utils.js +1 -25
  10. package/dist/cjs/rules/use-primitives/index.js +40 -35
  11. package/dist/cjs/rules/use-primitives/transformers/css-to-xcss.js +10 -3
  12. package/dist/cjs/rules/use-primitives/transformers/index.js +8 -1
  13. package/dist/cjs/rules/use-primitives/transformers/styled-component-to-primitive.js +68 -0
  14. package/dist/cjs/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js +16 -0
  15. package/dist/cjs/rules/use-primitives/utils/find-valid-jsx-usage-to-transform.js +39 -0
  16. package/dist/cjs/rules/use-primitives/utils/find-valid-styled-component-call.js +52 -0
  17. package/dist/cjs/rules/use-primitives/utils/index.js +21 -0
  18. package/dist/cjs/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +38 -0
  19. package/dist/cjs/rules/use-primitives/utils/is-valid-tag-name.js +2 -2
  20. package/dist/cjs/rules/use-primitives/utils/update-jsx-element-name.js +1 -1
  21. package/dist/cjs/rules/utils/get-import-name.js +30 -0
  22. package/dist/es2019/presets/all.codegen.js +2 -1
  23. package/dist/es2019/presets/recommended.codegen.js +2 -1
  24. package/dist/es2019/rules/index.codegen.js +3 -1
  25. package/dist/es2019/rules/use-heading-level-in-spotlight-card/index.js +49 -0
  26. package/dist/es2019/rules/use-href-in-link-item/index.js +3 -2
  27. package/dist/es2019/rules/use-href-in-link-item/utils.js +0 -24
  28. package/dist/es2019/rules/use-primitives/index.js +41 -37
  29. package/dist/es2019/rules/use-primitives/transformers/css-to-xcss.js +9 -6
  30. package/dist/es2019/rules/use-primitives/transformers/index.js +2 -1
  31. package/dist/es2019/rules/use-primitives/transformers/styled-component-to-primitive.js +59 -0
  32. package/dist/es2019/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js +14 -0
  33. package/dist/es2019/rules/use-primitives/utils/find-valid-jsx-usage-to-transform.js +32 -0
  34. package/dist/es2019/rules/use-primitives/utils/find-valid-styled-component-call.js +47 -0
  35. package/dist/es2019/rules/use-primitives/utils/index.js +3 -0
  36. package/dist/es2019/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +32 -0
  37. package/dist/es2019/rules/use-primitives/utils/is-valid-tag-name.js +1 -1
  38. package/dist/es2019/rules/use-primitives/utils/update-jsx-element-name.js +1 -1
  39. package/dist/es2019/rules/utils/get-import-name.js +24 -0
  40. package/dist/esm/presets/all.codegen.js +2 -1
  41. package/dist/esm/presets/recommended.codegen.js +2 -1
  42. package/dist/esm/rules/index.codegen.js +3 -1
  43. package/dist/esm/rules/use-heading-level-in-spotlight-card/index.js +57 -0
  44. package/dist/esm/rules/use-href-in-link-item/index.js +3 -2
  45. package/dist/esm/rules/use-href-in-link-item/utils.js +0 -24
  46. package/dist/esm/rules/use-primitives/index.js +41 -37
  47. package/dist/esm/rules/use-primitives/transformers/css-to-xcss.js +9 -2
  48. package/dist/esm/rules/use-primitives/transformers/index.js +2 -1
  49. package/dist/esm/rules/use-primitives/transformers/styled-component-to-primitive.js +61 -0
  50. package/dist/esm/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.js +16 -0
  51. package/dist/esm/rules/use-primitives/utils/find-valid-jsx-usage-to-transform.js +34 -0
  52. package/dist/esm/rules/use-primitives/utils/find-valid-styled-component-call.js +47 -0
  53. package/dist/esm/rules/use-primitives/utils/index.js +3 -0
  54. package/dist/esm/rules/use-primitives/utils/is-valid-css-properties-to-transform.js +32 -0
  55. package/dist/esm/rules/use-primitives/utils/is-valid-tag-name.js +1 -1
  56. package/dist/esm/rules/use-primitives/utils/update-jsx-element-name.js +1 -1
  57. package/dist/esm/rules/utils/get-import-name.js +24 -0
  58. package/dist/types/index.codegen.d.ts +2 -0
  59. package/dist/types/presets/all.codegen.d.ts +2 -1
  60. package/dist/types/presets/recommended.codegen.d.ts +2 -1
  61. package/dist/types/rules/index.codegen.d.ts +1 -0
  62. package/dist/types/rules/use-heading-level-in-spotlight-card/index.d.ts +4 -0
  63. package/dist/types/rules/use-href-in-link-item/utils.d.ts +0 -1
  64. package/dist/types/rules/use-primitives/transformers/css-to-xcss.d.ts +2 -1
  65. package/dist/types/rules/use-primitives/transformers/index.d.ts +1 -0
  66. package/dist/types/rules/use-primitives/transformers/styled-component-to-primitive.d.ts +13 -0
  67. package/dist/types/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.d.ts +1 -1
  68. package/dist/types/rules/use-primitives/utils/find-valid-jsx-usage-to-transform.d.ts +7 -0
  69. package/dist/types/rules/use-primitives/utils/find-valid-styled-component-call.d.ts +7 -0
  70. package/dist/types/rules/use-primitives/utils/index.d.ts +3 -0
  71. package/dist/types/rules/use-primitives/utils/is-valid-css-properties-to-transform.d.ts +3 -0
  72. package/dist/types/rules/use-primitives/utils/is-valid-tag-name.d.ts +1 -0
  73. package/dist/types/rules/use-primitives/utils/update-jsx-element-name.d.ts +1 -1
  74. package/dist/types/rules/utils/get-import-name.d.ts +2 -0
  75. package/dist/types-ts4.5/index.codegen.d.ts +2 -0
  76. package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -1
  77. package/dist/types-ts4.5/presets/recommended.codegen.d.ts +2 -1
  78. package/dist/types-ts4.5/rules/index.codegen.d.ts +1 -0
  79. package/dist/types-ts4.5/rules/use-heading-level-in-spotlight-card/index.d.ts +4 -0
  80. package/dist/types-ts4.5/rules/use-href-in-link-item/utils.d.ts +0 -1
  81. package/dist/types-ts4.5/rules/use-primitives/transformers/css-to-xcss.d.ts +2 -1
  82. package/dist/types-ts4.5/rules/use-primitives/transformers/index.d.ts +1 -0
  83. package/dist/types-ts4.5/rules/use-primitives/transformers/styled-component-to-primitive.d.ts +13 -0
  84. package/dist/types-ts4.5/rules/use-primitives/utils/convert-ast-object-expression-to-js-object.d.ts +1 -1
  85. package/dist/types-ts4.5/rules/use-primitives/utils/find-valid-jsx-usage-to-transform.d.ts +7 -0
  86. package/dist/types-ts4.5/rules/use-primitives/utils/find-valid-styled-component-call.d.ts +7 -0
  87. package/dist/types-ts4.5/rules/use-primitives/utils/index.d.ts +3 -0
  88. package/dist/types-ts4.5/rules/use-primitives/utils/is-valid-css-properties-to-transform.d.ts +3 -0
  89. package/dist/types-ts4.5/rules/use-primitives/utils/is-valid-tag-name.d.ts +1 -0
  90. package/dist/types-ts4.5/rules/use-primitives/utils/update-jsx-element-name.d.ts +1 -1
  91. package/dist/types-ts4.5/rules/utils/get-import-name.d.ts +2 -0
  92. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 8.18.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#64857](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/64857) [`1be24644c029`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/1be24644c029) - `use-primitives` is now capable of converting styled components. This is guarded by a config flag so this release is only a patch.
8
+
9
+ ## 8.18.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#65123](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/65123) [`f3b62a2c6bdd`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/f3b62a2c6bdd) - Add new rule to warn of rollout of required `headingLevel` prop in the `SpotlightCard` component of the onboarding package.
14
+
3
15
  ## 8.17.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -65,6 +65,7 @@ module.exports = {
65
65
  | <a href="./src/rules/no-unsupported-drag-and-drop-libraries/README.md">no-unsupported-drag-and-drop-libraries</a> | Disallow importing unsupported drag and drop modules. | Yes | | |
66
66
  | <a href="./src/rules/prefer-primitives/README.md">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
67
67
  | <a href="./src/rules/use-drawer-label/README.md">use-drawer-label</a> | Encourages to provide accessible name for Atlassian Design System Drawer component. | Yes | | Yes |
68
+ | <a href="./src/rules/use-heading-level-in-spotlight-card/README.md">use-heading-level-in-spotlight-card</a> | Inform developers of eventual requirement of `headingLevel` prop in `SpotlightCard` component. The heading level should be the appropriate level according to the surrounding context. | Yes | Yes | |
68
69
  | <a href="./src/rules/use-href-in-link-item/README.md">use-href-in-link-item</a> | Inform developers of eventual requirement of `href` prop in `LinkItem` component. Elements with a `link` role require an `href` attribute for users to properly navigate, particularly those using assistive technologies. If no valid `href` is required for your use case, consider using a `ButtonItem` instead. | Yes | Yes | Yes |
69
70
  | <a href="./src/rules/use-primitives/README.md">use-primitives</a> | Encourage the usage of primitives components. | | Yes | Yes |
70
71
  | <a href="./src/rules/use-visually-hidden/README.md">use-visually-hidden</a> | Enforce usage of the visually hidden component. | Yes | Yes | |
@@ -29,6 +29,7 @@ This plugin contains rules that should be used when working with the [Atlassian
29
29
  | <a href="#no-unsupported-drag-and-drop-libraries">no-unsupported-drag-and-drop-libraries</a> | Disallow importing unsupported drag and drop modules. | Yes | | |
30
30
  | <a href="#prefer-primitives">prefer-primitives</a> | Increase awareness of primitive components via code hints. Strictly used for education purposes and discoverability. To enforce usage please refer to the `use-primitives` rule. | | | |
31
31
  | <a href="#use-drawer-label">use-drawer-label</a> | Encourages to provide accessible name for Atlassian Design System Drawer component. | Yes | | Yes |
32
+ | <a href="#use-heading-level-in-spotlight-card">use-heading-level-in-spotlight-card</a> | Inform developers of eventual requirement of `headingLevel` prop in `SpotlightCard` component. The heading level should be the appropriate level according to the surrounding context. | Yes | Yes | |
32
33
  | <a href="#use-href-in-link-item">use-href-in-link-item</a> | Inform developers of eventual requirement of `href` prop in `LinkItem` component. Elements with a `link` role require an `href` attribute for users to properly navigate, particularly those using assistive technologies. If no valid `href` is required for your use case, consider using a `ButtonItem` instead. | Yes | Yes | Yes |
33
34
  | <a href="#use-primitives">use-primitives</a> | Encourage the usage of primitives components. | | Yes | Yes |
34
35
  | <a href="#use-visually-hidden">use-visually-hidden</a> | Enforce usage of the visually hidden component. | Yes | Yes | |
@@ -769,6 +770,27 @@ This rule will indicate user with warning to strongly recommend usage of either
769
770
  </Drawer>
770
771
  ```
771
772
 
773
+ ## use-heading-level-in-spotlight-card
774
+
775
+ The `SpotlightCard` component in `@atlaskit/onboarding` will be requiring the `headingLevel` prop in future releases.
776
+
777
+ <h3>Examples</h3>
778
+
779
+ #### Incorrect
780
+
781
+ ```tsx
782
+ <SpotlightCard heading="Heading">Spotlight card contents</SpotlightCard>
783
+ ^^^^^^^^^^^^^
784
+ ```
785
+
786
+ #### Correct
787
+
788
+ ```tsx
789
+ <SpotlightCard heading="Heading" headingLevel={2}>
790
+ Spotlight card contents
791
+ </SpotlightCard>
792
+ ```
793
+
772
794
  ## use-href-in-link-item
773
795
 
774
796
  The `LinkItem` component in `@atlaskit/menu` will be requiring the `href` prop in future releases. If no valid `href` prop is required, consider using the `ButtonItem` component.
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::594898d8c5dc8b9a5610d62e7f300a53>>
9
+ * @codegen <<SignedSource::37a857efd0971ab26170d5f1f526279b>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -28,6 +28,7 @@ var _default = exports.default = {
28
28
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
29
29
  '@atlaskit/design-system/prefer-primitives': 'warn',
30
30
  '@atlaskit/design-system/use-drawer-label': 'warn',
31
+ '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
31
32
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
32
33
  '@atlaskit/design-system/use-primitives': 'warn',
33
34
  '@atlaskit/design-system/use-visually-hidden': 'error'
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  /**
8
8
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
9
- * @codegen <<SignedSource::240c678d4f10d97618541f35d79e1c71>>
9
+ * @codegen <<SignedSource::b3bce8efb2db1fed84370af608ca0d4c>>
10
10
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
11
11
  */
12
12
  var _default = exports.default = {
@@ -23,6 +23,7 @@ var _default = exports.default = {
23
23
  '@atlaskit/design-system/no-unsafe-design-token-usage': 'error',
24
24
  '@atlaskit/design-system/no-unsupported-drag-and-drop-libraries': 'error',
25
25
  '@atlaskit/design-system/use-drawer-label': 'warn',
26
+ '@atlaskit/design-system/use-heading-level-in-spotlight-card': 'warn',
26
27
  '@atlaskit/design-system/use-href-in-link-item': 'warn',
27
28
  '@atlaskit/design-system/use-visually-hidden': 'error'
28
29
  }
@@ -21,12 +21,13 @@ var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./no-unsafe-desi
21
21
  var _noUnsupportedDragAndDropLibraries = _interopRequireDefault(require("./no-unsupported-drag-and-drop-libraries"));
22
22
  var _preferPrimitives = _interopRequireDefault(require("./prefer-primitives"));
23
23
  var _useDrawerLabel = _interopRequireDefault(require("./use-drawer-label"));
24
+ var _useHeadingLevelInSpotlightCard = _interopRequireDefault(require("./use-heading-level-in-spotlight-card"));
24
25
  var _useHrefInLinkItem = _interopRequireDefault(require("./use-href-in-link-item"));
25
26
  var _usePrimitives = _interopRequireDefault(require("./use-primitives"));
26
27
  var _useVisuallyHidden = _interopRequireDefault(require("./use-visually-hidden"));
27
28
  /**
28
29
  * THIS FILE WAS CREATED VIA CODEGEN DO NOT MODIFY {@see http://go/af-codegen}
29
- * @codegen <<SignedSource::8927e5adaec5639c9712dbfb26968de4>>
30
+ * @codegen <<SignedSource::e2cc357c90120dbbd89b2928dba968c0>>
30
31
  * @codegenCommand yarn workspace @atlaskit/eslint-plugin-design-system codegen
31
32
  */
32
33
  var _default = exports.default = {
@@ -46,6 +47,7 @@ var _default = exports.default = {
46
47
  'no-unsupported-drag-and-drop-libraries': _noUnsupportedDragAndDropLibraries.default,
47
48
  'prefer-primitives': _preferPrimitives.default,
48
49
  'use-drawer-label': _useDrawerLabel.default,
50
+ 'use-heading-level-in-spotlight-card': _useHeadingLevelInSpotlightCard.default,
49
51
  'use-href-in-link-item': _useHrefInLinkItem.default,
50
52
  'use-primitives': _usePrimitives.default,
51
53
  'use-visually-hidden': _useVisuallyHidden.default
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.headingLevelRequiredSuggestionText = exports.default = void 0;
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ var _createRule = require("../utils/create-rule");
9
+ var _getImportName = require("../utils/get-import-name");
10
+ // eslint-disable-next-line import/no-extraneous-dependencies
11
+
12
+ var headingLevelRequiredSuggestionText = exports.headingLevelRequiredSuggestionText = 'Add a `headingLevel` that is of a contextually relevant level.';
13
+ var rule = (0, _createRule.createLintRule)({
14
+ meta: {
15
+ name: 'use-heading-level-in-spotlight-card',
16
+ type: 'suggestion',
17
+ fixable: 'code',
18
+ docs: {
19
+ description: 'Inform developers of eventual requirement of `headingLevel` prop in `SpotlightCard` component. The heading level should be the appropriate level according to the surrounding context.',
20
+ recommended: true,
21
+ severity: 'warn'
22
+ },
23
+ messages: {
24
+ headingLevelRequired: headingLevelRequiredSuggestionText
25
+ }
26
+ },
27
+ create: function create(context) {
28
+ return {
29
+ JSXElement: function JSXElement(node) {
30
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXElement')) {
31
+ return;
32
+ }
33
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node.openingElement.name, 'JSXIdentifier')) {
34
+ return;
35
+ }
36
+
37
+ // Get the name of the SpotlightCard import
38
+ var spotlightCardImportName = (0, _getImportName.getImportName)(context.getScope(), '@atlaskit/onboarding', 'SpotlightCard');
39
+ if (node.openingElement.name.name === spotlightCardImportName) {
40
+ // and if `heading` exists and `headingLevel` prop does not exist
41
+ var spotlightCardProps = node.openingElement.attributes.filter(function (attr) {
42
+ return (0, _eslintCodemodUtils.isNodeOfType)(attr, 'JSXAttribute');
43
+ }).filter(function (attr) {
44
+ return attr.name.type === 'JSXIdentifier';
45
+ });
46
+ var heading = spotlightCardProps.find(function (attr) {
47
+ return attr.name.name === 'heading';
48
+ });
49
+ var headingLevel = spotlightCardProps.find(function (attr) {
50
+ return attr.name.name === 'headingLevel';
51
+ });
52
+ if (heading && !headingLevel) {
53
+ context.report({
54
+ node: node,
55
+ messageId: 'headingLevelRequired'
56
+ });
57
+ }
58
+ }
59
+ }
60
+ };
61
+ }
62
+ });
63
+ var _default = exports.default = rule;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.hrefRequiredSuggestionText = exports.default = void 0;
7
7
  var _eslintCodemodUtils = require("eslint-codemod-utils");
8
8
  var _createRule = require("../utils/create-rule");
9
+ var _getImportName = require("../utils/get-import-name");
9
10
  var _utils = require("./utils");
10
11
  // eslint-disable-next-line import/no-extraneous-dependencies
11
12
 
@@ -52,7 +53,7 @@ var rule = (0, _createRule.createLintRule)({
52
53
  }
53
54
 
54
55
  // Get the name of the LinkItem import
55
- var linkItemImportName = customDefaultLinkItemSpecifier || (0, _utils.getLinkItemImportName)(context.getScope());
56
+ var linkItemImportName = customDefaultLinkItemSpecifier || (0, _getImportName.getImportName)(context.getScope(), '@atlaskit/menu', 'LinkItem');
56
57
  if (node.openingElement.name.name === linkItemImportName) {
57
58
  // and if href prop does not exist
58
59
  var linkProps = node.openingElement.attributes.filter(function (attr) {
@@ -3,35 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.insertButtonItemImport = exports.insertButtonItemDefaultImport = exports.hrefHasInvalidValue = exports.hasImportOfName = exports.getUniqueButtonItemName = exports.getLinkItemImportName = void 0;
6
+ exports.insertButtonItemImport = exports.insertButtonItemDefaultImport = exports.hrefHasInvalidValue = exports.hasImportOfName = exports.getUniqueButtonItemName = void 0;
7
7
  var _eslintCodemodUtils = require("eslint-codemod-utils");
8
8
  var _findInParent = require("../utils/find-in-parent");
9
9
  // eslint-disable-next-line import/no-extraneous-dependencies
10
10
 
11
- var getLinkItemImportName = exports.getLinkItemImportName = function getLinkItemImportName(scope) {
12
- var traversingScope = scope;
13
- var matchedVariable;
14
- while (traversingScope && traversingScope.type !== 'global') {
15
- matchedVariable = traversingScope.variables.find(function (variable) {
16
- var _variable$defs;
17
- var def = (_variable$defs = variable.defs) === null || _variable$defs === void 0 ? void 0 : _variable$defs[0];
18
- if (!def || !(def !== null && def !== void 0 && def.node) || !(0, _eslintCodemodUtils.isNodeOfType)(def.node, 'ImportSpecifier') || !def.parent || !(0, _eslintCodemodUtils.isNodeOfType)(def.parent, 'ImportDeclaration')) {
19
- return;
20
- }
21
- return def.parent.source.value === '@atlaskit/menu' && def.node.imported.name === 'LinkItem';
22
- });
23
- if (matchedVariable) {
24
- break;
25
- }
26
- traversingScope = traversingScope.upper;
27
- }
28
- if (!matchedVariable) {
29
- return null;
30
- } else {
31
- var _matchedVariable$defs;
32
- return (_matchedVariable$defs = matchedVariable.defs) === null || _matchedVariable$defs === void 0 ? void 0 : _matchedVariable$defs[0].node.local.name;
33
- }
34
- };
35
11
  var invalidHrefValues = ['', '#', null, undefined];
36
12
  var hrefHasInvalidValue = exports.hrefHasInvalidValue = function hrefHasInvalidValue(scope, href) {
37
13
  // If doesn't exist,
@@ -1,14 +1,19 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.default = void 0;
7
8
  var _eslintCodemodUtils = require("eslint-codemod-utils");
9
+ var _assign = _interopRequireDefault(require("lodash/assign"));
8
10
  var _createRule = require("../utils/create-rule");
9
11
  var _transformers = require("./transformers");
10
12
  var _utils = require("./utils");
11
13
  var boxDocsUrl = 'https://atlassian.design/components/primitives/box';
14
+ var defaultConfig = {
15
+ preview: false
16
+ };
12
17
  var rule = (0, _createRule.createLintRule)({
13
18
  meta: {
14
19
  name: 'use-primitives',
@@ -21,11 +26,43 @@ var rule = (0, _createRule.createLintRule)({
21
26
  severity: 'warn'
22
27
  },
23
28
  messages: {
24
- preferPrimitivesBox: "This \"{{element}}\" may be able to be replaced with a \"Box\". See ".concat(boxDocsUrl, " for guidance.")
29
+ preferPrimitivesBox: "This element can be replaced with a \"Box\" primitive. See ".concat(boxDocsUrl, " for additional guidance.")
25
30
  }
26
31
  },
27
32
  create: function create(context) {
33
+ var mergedConfig = (0, _assign.default)({}, defaultConfig, context.options[0]);
28
34
  return {
35
+ // transforms styled.<html>(...) usages
36
+ CallExpression: function CallExpression(node) {
37
+ if (!mergedConfig.preview) {
38
+ return;
39
+ }
40
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'CallExpression')) {
41
+ return;
42
+ }
43
+ var styledComponentVariableRef = (0, _utils.findValidStyledComponentCall)(node);
44
+ if (!styledComponentVariableRef || !(0, _eslintCodemodUtils.isNodeOfType)(styledComponentVariableRef.id, 'Identifier') || !(0, _utils.isValidCssPropertiesToTransform)(node)) {
45
+ return;
46
+ }
47
+ var styledComponentJsxRef = (0, _utils.findValidJsxUsageToTransform)(styledComponentVariableRef.id.name, context.getScope());
48
+ if (!styledComponentJsxRef) {
49
+ return;
50
+ }
51
+
52
+ // if we have both references at this point then we can offer a fix \o/
53
+ context.report({
54
+ node: styledComponentVariableRef,
55
+ messageId: 'preferPrimitivesBox',
56
+ suggest: [{
57
+ desc: "Convert ".concat(styledComponentVariableRef.id.name, " to Box"),
58
+ fix: (0, _transformers.styledComponentToPrimitive)({
59
+ stylesRef: styledComponentVariableRef,
60
+ jsxRef: styledComponentJsxRef
61
+ }, context)
62
+ }]
63
+ });
64
+ },
65
+ // transforms <div css={...}> usages
29
66
  JSXOpeningElement: function JSXOpeningElement(node) {
30
67
  if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXOpeningElement')) {
31
68
  return;
@@ -97,42 +134,10 @@ var shouldSuggestBox = function shouldSuggestBox(node, context
97
134
  // Find where `cssVariableName` is defined. We're looking for `const myStyles = css({...})`
98
135
  var cssVariableDefinition = (0, _eslintCodemodUtils.getIdentifierInParentScope)(context.getScope(), cssVariableName);
99
136
  var cssVariableValue = (0, _utils.getVariableDefinitionValue)(cssVariableDefinition);
100
-
101
137
  // Check if `cssVariableValue` is a function called `css()`
102
- if (!(0, _utils.isFunctionNamed)(cssVariableValue, 'css')) {
103
- return false;
104
- }
105
-
106
- // get the `{}` in `css({})`
107
- // Zero indexed
108
- var cssObjectExpression = (0, _utils.getFunctionArgumentAtPos)(cssVariableValue, 0);
109
-
110
- // Bail on empty `css()` calls
111
- if (!cssObjectExpression) {
112
- return false;
113
- }
114
- var cssObject = (0, _utils.convertASTObjectExpressionToJSObject)(cssObjectExpression);
115
-
116
- // Bail if there are less or more than 1 styles defined
117
- if (Object.keys(cssObject).length !== 1) {
118
- return false;
119
- }
120
-
121
- // NOTE: Our approach with this lint rule is to strictly whitelist css properties we can map.
122
- // It means we have to provide mappings for everything (e.g. `display: block`).
123
- // However, from a maker's experience, it's much better that the rule doesn't report (if we miss a mapping)
124
- // than the rule reporting on things that can't be mapped.
125
- var containsOnlyValidStyles = Object.keys(cssObject).every(function (styleProperty) {
126
- var styleValue = cssObject[styleProperty];
127
- return _transformers.supportedStylesMap[styleProperty] &&
128
- // Is the key something we can map
129
- _transformers.supportedStylesMap[styleProperty][styleValue] // Is the value something we can map
130
- ;
131
- });
132
-
133
- if (!containsOnlyValidStyles) {
138
+ if (!cssVariableValue || !(0, _utils.isFunctionNamed)(cssVariableValue, 'css')) {
134
139
  return false;
135
140
  }
136
- return true;
141
+ return (0, _utils.isValidCssPropertiesToTransform)(cssVariableValue.node.init);
137
142
  };
138
143
  var _default = exports.default = rule;
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.supportedStylesMap = exports.spaceTokenMap = exports.cssToXcssTransformer = void 0;
7
+ exports.supportedStylesMap = exports.styledObjectToXcssTokens = exports.spaceTokenMap = exports.cssToXcssTransformer = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _eslintCodemodUtils = require("eslint-codemod-utils");
10
10
  var _utils = require("../utils");
@@ -36,7 +36,14 @@ var cssToXcssTransformer = exports.cssToXcssTransformer = function cssToXcssTran
36
36
  var cssObjectExpression = (0, _utils.getFunctionArgumentAtPos)(cssVariableValue, 0);
37
37
  return [
38
38
  // Update `css` function name to `xcss`.
39
- fixer.replaceText(cssVariableValue.node.init.callee, (0, _eslintCodemodUtils.identifier)('xcss').toString())].concat((0, _toConsumableArray2.default)(cssObjectExpression.properties.map(function (entry) {
39
+ fixer.replaceText(cssVariableValue.node.init.callee, (0, _eslintCodemodUtils.identifier)('xcss').toString())].concat((0, _toConsumableArray2.default)(styledObjectToXcssTokens(cssObjectExpression, fixer)));
40
+ };
41
+
42
+ // Update css object values to xcss values. e.g. `'8px'` -> `'space.100'`
43
+ // Note: `properties` in this context is a group of AST nodes that make up a key/value pair in an object.
44
+ // e.g. `padding: '8px'`. For clarity, it's renamed to `entry` inside the `.map()`.
45
+ var styledObjectToXcssTokens = exports.styledObjectToXcssTokens = function styledObjectToXcssTokens(styles, fixer) {
46
+ return styles.properties.map(function (entry) {
40
47
  if (!(0, _eslintCodemodUtils.isNodeOfType)(entry, 'Property')) {
41
48
  return;
42
49
  }
@@ -51,7 +58,7 @@ var cssToXcssTransformer = exports.cssToXcssTransformer = function cssToXcssTran
51
58
  return;
52
59
  }
53
60
  return fixer.replaceText(entry.value, (0, _eslintCodemodUtils.literal)("'".concat(supportedStylesMap[entry.key.name][value], "'")).toString());
54
- })));
61
+ });
55
62
  };
56
63
  var spaceTokenMap = exports.spaceTokenMap = {
57
64
  '0px': 'space.0',
@@ -21,6 +21,12 @@ Object.defineProperty(exports, "spaceTokenMap", {
21
21
  return _cssToXcss.spaceTokenMap;
22
22
  }
23
23
  });
24
+ Object.defineProperty(exports, "styledComponentToPrimitive", {
25
+ enumerable: true,
26
+ get: function get() {
27
+ return _styledComponentToPrimitive.styledComponentToPrimitive;
28
+ }
29
+ });
24
30
  Object.defineProperty(exports, "supportedStylesMap", {
25
31
  enumerable: true,
26
32
  get: function get() {
@@ -28,4 +34,5 @@ Object.defineProperty(exports, "supportedStylesMap", {
28
34
  }
29
35
  });
30
36
  var _cssToXcss = require("./css-to-xcss");
31
- var _jsxElementToBox = require("./jsx-element-to-box");
37
+ var _jsxElementToBox = require("./jsx-element-to-box");
38
+ var _styledComponentToPrimitive = require("./styled-component-to-primitive");
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.styledComponentToPrimitive = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
10
+ var _utils = require("../utils");
11
+ var _cssToXcss = require("./css-to-xcss");
12
+ /**
13
+ * All required validation steps have been taken care of before this
14
+ * transformer is called, so it just goes ahead providing all necessary fixes
15
+ */
16
+ var styledComponentToPrimitive = exports.styledComponentToPrimitive = function styledComponentToPrimitive(_ref, context) {
17
+ var stylesRef = _ref.stylesRef,
18
+ jsxRef = _ref.jsxRef;
19
+ return function (fixer) {
20
+ // generates the new variable name: MyComponent -> myComponentStyles
21
+ var calculatedStylesVariableName = (0, _eslintCodemodUtils.isNodeOfType)(stylesRef.id, 'Identifier') && "".concat(stylesRef.id.name.replace(stylesRef.id.name[0], stylesRef.id.name[0].toLowerCase()), "Styles");
22
+ if (!calculatedStylesVariableName) {
23
+ return [];
24
+ }
25
+ var importFixes = (0, _utils.upsertImportDeclaration)({
26
+ packageName: '@atlaskit/primitives',
27
+ specifiers: ['Box', 'xcss']
28
+ }, context, fixer);
29
+ var stylesFixes = convertStyledComponentToXcss(stylesRef, calculatedStylesVariableName, fixer);
30
+ var jsxFixes = convertJsxCallSite(jsxRef, calculatedStylesVariableName, fixer);
31
+ return [importFixes].concat(stylesFixes, jsxFixes).filter(function (fix) {
32
+ return Boolean(fix);
33
+ }); // Some of the transformers can return arrays with undefined, so filter them out
34
+ };
35
+ };
36
+
37
+ var convertStyledComponentToXcss = function convertStyledComponentToXcss(stylesRef, newStylesVariableName, fixer) {
38
+ var fixes = [];
39
+
40
+ // renames the variable from MyComponent to myComponentStyles
41
+ fixes.push(fixer.replaceText(stylesRef.id, newStylesVariableName));
42
+
43
+ // renames the function call from styled.<tag> to xcss
44
+ if (stylesRef.init && (0, _eslintCodemodUtils.isNodeOfType)(stylesRef.init, 'CallExpression')) {
45
+ fixes.push(fixer.replaceText(stylesRef.init.callee, 'xcss'));
46
+ }
47
+
48
+ // converts CSS values to XCSS-compatible tokens
49
+ if (stylesRef.init && (0, _eslintCodemodUtils.isNodeOfType)(stylesRef.init, 'CallExpression')) {
50
+ var objectExpression = stylesRef.init.arguments[0];
51
+ if ((0, _eslintCodemodUtils.isNodeOfType)(objectExpression, 'ObjectExpression')) {
52
+ fixes.push.apply(fixes, (0, _toConsumableArray2.default)((0, _cssToXcss.styledObjectToXcssTokens)(objectExpression, fixer)));
53
+ }
54
+ }
55
+ return fixes;
56
+ };
57
+ var convertJsxCallSite = function convertJsxCallSite(jsxRef, newStylesVariableName, fixer) {
58
+ var fixes = [];
59
+
60
+ // renames the JSX call site
61
+ if ((0, _eslintCodemodUtils.isNodeOfType)(jsxRef.parent, 'JSXElement')) {
62
+ fixes.push.apply(fixes, (0, _toConsumableArray2.default)((0, _utils.updateJSXElementName)(jsxRef.parent, 'Box', fixer)));
63
+ }
64
+
65
+ // adds xcss prop
66
+ fixes.push(fixer.insertTextAfter(jsxRef.name, " xcss={".concat(newStylesVariableName, "}")));
67
+ return fixes;
68
+ };
@@ -12,6 +12,22 @@ var _eslintCodemodUtils = require("eslint-codemod-utils");
12
12
  */
13
13
  var convertASTObjectExpressionToJSObject = exports.convertASTObjectExpressionToJSObject = function convertASTObjectExpressionToJSObject(styles) {
14
14
  var styleObj = {};
15
+
16
+ // if we see any spread props we stop and return false to indicate this is unsupported
17
+ if (!styles.properties.every(function (prop) {
18
+ return (0, _eslintCodemodUtils.isNodeOfType)(prop, 'Property');
19
+ })) {
20
+ return false;
21
+ }
22
+
23
+ // TODO: We need to harden this logic.
24
+ // It currently generates a false positive for:
25
+ // styled.div({
26
+ // marginTop: "0px",
27
+ // marginBottom: token("space.100", "8px"),
28
+ // })
29
+ // as the value for `marginBottom` is not a string, so it is just skipped
30
+ // from the resulting map and this causes the rule to trigger when it shouldn't
15
31
  styles.properties.forEach(function (prop) {
16
32
  if (!(0, _eslintCodemodUtils.isNodeOfType)(prop, 'Property')) {
17
33
  return;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.findValidJsxUsageToTransform = void 0;
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ /**
9
+ * Given a component name finds its JSX usages and performs some
10
+ * additional validations to ensure transformation can be done correctly
11
+ */
12
+ var findValidJsxUsageToTransform = exports.findValidJsxUsageToTransform = function findValidJsxUsageToTransform(componentName, scope) {
13
+ var variableDeclaration = scope.variables.find(function (v) {
14
+ return v.name === componentName;
15
+ });
16
+ if (!variableDeclaration) {
17
+ return;
18
+ }
19
+
20
+ // length here should be exactly 2 to indicate only two references:
21
+ // one being the variable declaration itself
22
+ // second being the JSX call site
23
+ // we might consider handling multiple local JSX call sites in the future
24
+ // but "this is good enough for now"™️
25
+ if (variableDeclaration.references.length !== 2) {
26
+ return;
27
+ }
28
+ var jsxUsage = variableDeclaration.references[1].identifier;
29
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(jsxUsage, 'JSXIdentifier')) {
30
+ return;
31
+ }
32
+ var jsxOpeningElement = jsxUsage.parent;
33
+ // we could relatively easily support some safe attributes like
34
+ // "id" or "testId" but support will be expanded as we go
35
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(jsxOpeningElement, 'JSXOpeningElement') || jsxOpeningElement.attributes.length > 0) {
36
+ return;
37
+ }
38
+ return jsxOpeningElement;
39
+ };
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.findValidStyledComponentCall = void 0;
7
+ var _eslintCodemodUtils = require("eslint-codemod-utils");
8
+ var _isValidTagName = require("./is-valid-tag-name");
9
+ /**
10
+ * returns a variable reference if preconditions are favourable for
11
+ * the transformation to proceed, undefined otherwise.
12
+ */
13
+
14
+ var findValidStyledComponentCall = exports.findValidStyledComponentCall = function findValidStyledComponentCall(node) {
15
+ // halts unless we are dealing with a styled component
16
+ if (!isStyledCallExpression(node)) {
17
+ return;
18
+ }
19
+ // halts if the component is being exported directly
20
+ if ((0, _eslintCodemodUtils.closestOfType)(node, 'ExportNamedDeclaration')) {
21
+ return;
22
+ }
23
+ var styledComponentVariableRef = node.parent;
24
+ // halts if the styled component is not assigned to a variable immediately
25
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(styledComponentVariableRef, 'VariableDeclarator')) {
26
+ return;
27
+ }
28
+ return styledComponentVariableRef;
29
+ };
30
+
31
+ /**
32
+ * Some verbose precondition checks but all it does is check
33
+ * a call expression is of form `styled.div` or `styled2.div`
34
+ *
35
+ * In the future it could be enhanced to double check `styled` and `styled2`
36
+ * are Compiled imports but as is should work for the majority of use cases
37
+ */
38
+ var isStyledCallExpression = function isStyledCallExpression(call) {
39
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(call, 'CallExpression')) {
40
+ return false;
41
+ }
42
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(call.callee, 'MemberExpression')) {
43
+ return false;
44
+ }
45
+ if (!(0, _eslintCodemodUtils.isNodeOfType)(call.callee.object, 'Identifier') || !(0, _eslintCodemodUtils.isNodeOfType)(call.callee.property, 'Identifier')) {
46
+ return false;
47
+ }
48
+ if (/^styled2?$/.test(call.callee.object.name) && _isValidTagName.validPrimitiveElements.has(call.callee.property.name)) {
49
+ return true;
50
+ }
51
+ return false;
52
+ };
@@ -15,6 +15,18 @@ Object.defineProperty(exports, "convertASTObjectExpressionToJSObject", {
15
15
  return _convertAstObjectExpressionToJsObject.convertASTObjectExpressionToJSObject;
16
16
  }
17
17
  });
18
+ Object.defineProperty(exports, "findValidJsxUsageToTransform", {
19
+ enumerable: true,
20
+ get: function get() {
21
+ return _findValidJsxUsageToTransform.findValidJsxUsageToTransform;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "findValidStyledComponentCall", {
25
+ enumerable: true,
26
+ get: function get() {
27
+ return _findValidStyledComponentCall.findValidStyledComponentCall;
28
+ }
29
+ });
18
30
  Object.defineProperty(exports, "getAttributeValueIdentifier", {
19
31
  enumerable: true,
20
32
  get: function get() {
@@ -51,6 +63,12 @@ Object.defineProperty(exports, "isFunctionNamed", {
51
63
  return _isFunctionNamed.isFunctionNamed;
52
64
  }
53
65
  });
66
+ Object.defineProperty(exports, "isValidCssPropertiesToTransform", {
67
+ enumerable: true,
68
+ get: function get() {
69
+ return _isValidCssPropertiesToTransform.isValidCssPropertiesToTransform;
70
+ }
71
+ });
54
72
  Object.defineProperty(exports, "isValidTagName", {
55
73
  enumerable: true,
56
74
  get: function get() {
@@ -77,12 +95,15 @@ Object.defineProperty(exports, "upsertImportDeclaration", {
77
95
  });
78
96
  var _containsOnlySupportedAttrs = require("./contains-only-supported-attrs");
79
97
  var _convertAstObjectExpressionToJsObject = require("./convert-ast-object-expression-to-js-object");
98
+ var _findValidJsxUsageToTransform = require("./find-valid-jsx-usage-to-transform");
99
+ var _findValidStyledComponentCall = require("./find-valid-styled-component-call");
80
100
  var _getAttributeValueIdentifier = require("./get-attribute-value-identifier");
81
101
  var _getFunctionArgumentAtPos = require("./get-function-argument-at-pos");
82
102
  var _getJsxAttributeByName = require("./get-jsx-attribute-by-name");
83
103
  var _getVariableDefinitionValue = require("./get-variable-definition-value");
84
104
  var _getVariableUsageCount = require("./get-variable-usage-count");
85
105
  var _isFunctionNamed = require("./is-function-named");
106
+ var _isValidCssPropertiesToTransform = require("./is-valid-css-properties-to-transform");
86
107
  var _isValidTagName = require("./is-valid-tag-name");
87
108
  var _updateJsxAttributeByName = require("./update-jsx-attribute-by-name");
88
109
  var _updateJsxElementName = require("./update-jsx-element-name");