@bigbinary/eslint-plugin-neeto 1.1.19 → 1.1.21

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 (3) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +168 -45
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -113,6 +113,7 @@ module.exports = {
113
113
  - [use-functions-and-hooks-from-neeto-commons-frontend.md](./docs/src/rules/use-functions-and-hooks-from-neeto-commons-frontend.md)
114
114
  - [zustand-use-with-immutable-actions-wrapper-inside-create](./docs/src/rules/zustand-use-with-immutable-actions-wrapper-inside-create.md)
115
115
  - [add-required-peer-dependencies](./docs/src/rules/add-required-peer-dependencies.md)
116
+ - [move-spread-attributes-to-top-position](./docs/src/rules/move-spread-attributes-to-top-position.md)
116
117
 
117
118
  ## Other references
118
119
 
package/dist/index.js CHANGED
@@ -151,7 +151,8 @@
151
151
  "@bigbinary/neeto/merge-spread-attributes": "error",
152
152
  "@bigbinary/neeto/props-inside-spread-attributes-should-be-sorted": "error",
153
153
  "@bigbinary/neeto/props-with-different-key-value-should-be-outside-spread-attribute": "error",
154
- "@bigbinary/neeto/use-common-constants": "warn"
154
+ "@bigbinary/neeto/use-common-constants": "warn",
155
+ "@bigbinary/neeto/move-spread-attributes-to-top-position": "error"
155
156
  };
156
157
 
157
158
  var recommended = {
@@ -547,6 +548,7 @@
547
548
  var USE_WITH_T_HOC_IN_DUMB_COMPONENTS = 'Use "withT" HOC from "neeto-commons-frontend" instead of useTranslation hook in Dumb components';
548
549
  var NO_WITH_T_IN_SMART_COMPONENTS = '"withT" HOC should only be used in dumb components. "useTranslation" hook should be used here.';
549
550
  var USE_STANDARD_DATE_TIME_FORMATS = 'Use "dateFormat/timeFormat" from "@bigbinary/neeto-commons-frontend/utils" instead. Refer: https://github.com/bigbinary/neeto-commons-frontend/blob/main/docs/utils/README.md#dateformattimeformat';
551
+ var MOVE_SPREAD_ATTRIBUTES_TO_TOP = "Move spread attribute to top";
550
552
 
551
553
  var PACKAGES_TO_CHECK = ["@bigbinary/neeto-molecules", "@bigbinary/neetoui", "@bigbinary/neeto-commons-frontend"];
552
554
 
@@ -3885,7 +3887,7 @@
3885
3887
  name: ramda.test(PASCAL_CASE_REGEX)
3886
3888
  }
3887
3889
  };
3888
- var EXPORTED_WITH_T_PATTERN = {
3890
+ var EXPORTED_WITH_T_PATTERN$1 = {
3889
3891
  type: TYPES.EXPORT_DEFAULT_DECLARATION,
3890
3892
  declaration: {
3891
3893
  type: TYPES.CALL_EXPRESSION,
@@ -4484,7 +4486,7 @@
4484
4486
  if (!isInsideComponentsDirectory(context)) return;
4485
4487
  var componentNodes = findMatchingNodesDeep(node.body, COMPONENT_PATTERN);
4486
4488
  if (ramda.isEmpty(componentNodes)) return;
4487
- var isExportedWithT = patternExistsDeep(EXPORTED_WITH_T_PATTERN, node);
4489
+ var isExportedWithT = patternExistsDeep(EXPORTED_WITH_T_PATTERN$1, node);
4488
4490
  componentNodes.forEach(function (node) {
4489
4491
  var tFunctionMemeberExpressionNodes = findMatchingNodesDeep(node, T_FUNCTION_MEMBER_EXPRESSION_PATTERN);
4490
4492
  tFunctionMemeberExpressionNodes.forEach(function (node) {
@@ -6537,6 +6539,12 @@
6537
6539
  type: TYPES.IMPORT_SPECIFIER
6538
6540
  }]
6539
6541
  };
6542
+
6543
+ // const Component = withT(({ t, userName, ...otherProps }, randomProps) => {
6544
+ // const a = useRef();
6545
+ // const [isOpen, setIsOpen] = useState(false);
6546
+ // return (t("Hello"));
6547
+ // });
6540
6548
  var WITH_T_HOC_PATTERN = {
6541
6549
  type: TYPES.VARIABLE_DECLARATION,
6542
6550
  kind: "const",
@@ -6563,11 +6571,107 @@
6563
6571
  }]
6564
6572
  };
6565
6573
 
6574
+ // export default withT(Component);
6575
+ var EXPORTED_WITH_T_PATTERN = {
6576
+ type: TYPES.EXPORT_DEFAULT_DECLARATION,
6577
+ declaration: {
6578
+ type: TYPES.CALL_EXPRESSION,
6579
+ callee: {
6580
+ type: TYPES.IDENTIFIER,
6581
+ name: "withT"
6582
+ },
6583
+ arguments: ramda.any(pure.matches({
6584
+ type: TYPES.IDENTIFIER,
6585
+ name: ramda.test(PASCAL_CASE_REGEX)
6586
+ }))
6587
+ }
6588
+ };
6589
+ var SMART_COMPONENT_PATTERN = {
6590
+ type: TYPES.VARIABLE_DECLARATION,
6591
+ kind: "const",
6592
+ declarations: [{
6593
+ type: TYPES.VARIABLE_DECLARATOR,
6594
+ init: {
6595
+ type: TYPES.ARROW_FUNCTION_EXPRESSION,
6596
+ body: {
6597
+ type: TYPES.BLOCK_STATEMENT,
6598
+ body: function body(_body2) {
6599
+ return _body2.length >= 2;
6600
+ }
6601
+ }
6602
+ },
6603
+ id: {
6604
+ type: TYPES.IDENTIFIER,
6605
+ name: ramda.test(PASCAL_CASE_REGEX)
6606
+ }
6607
+ }]
6608
+ };
6609
+
6610
+ var getPropsCode = function getPropsCode(context, arrowFunctionExpression, props) {
6611
+ if (ramda.isEmpty(arrowFunctionExpression.params)) return "";
6612
+ if (props.type === TYPES.IDENTIFIER) {
6613
+ return "{...".concat(getCode$1(context, props), " }");
6614
+ }
6615
+ if (props.type === TYPES.OBJECT_PATTERN) {
6616
+ var _props$properties, _props$properties2, _props$properties2$0$;
6617
+ if (((_props$properties = props.properties) === null || _props$properties === void 0 ? void 0 : _props$properties.length) === 1 && ((_props$properties2 = props.properties) === null || _props$properties2 === void 0 ? void 0 : (_props$properties2$0$ = _props$properties2[0].value) === null || _props$properties2$0$ === void 0 ? void 0 : _props$properties2$0$.name) === "t") {
6618
+ return "";
6619
+ }
6620
+ return "{".concat(props.properties.map(function (property) {
6621
+ return getCode$1(context, property);
6622
+ }).filter(pure.isNot("t")).join(", "), " }");
6623
+ }
6624
+ return "";
6625
+ };
6626
+ var getCodeWithUseTranslationHook = function getCodeWithUseTranslationHook(context, arrowFunctionExpression) {
6627
+ var _arrowFunctionExpress = _toArray(arrowFunctionExpression.params),
6628
+ props = _arrowFunctionExpress[0],
6629
+ restParams = _arrowFunctionExpress.slice(1);
6630
+ var codeInsideBody = getCode$1(context, arrowFunctionExpression.body);
6631
+ var codeWithUseTranslation = insertTextAfterPosition(0, codeInsideBody, "const { t } = useTranslation();\n");
6632
+ var updatedProps = getPropsCode(context, arrowFunctionExpression, props);
6633
+ var replacedCodeWithUseTranslation = "(".concat(updatedProps).concat(ramda.isEmpty(restParams) ? "" : "".concat(pure.isNotEmpty(updatedProps) ? ", " : "{}, ").concat(restParams.map(function (param) {
6634
+ return getCode$1(context, param);
6635
+ }).join(", ")), ") => ").concat(codeWithUseTranslation);
6636
+ return replacedCodeWithUseTranslation;
6637
+ };
6638
+ var createUseTranslationImport = function createUseTranslationImport(context, fixer) {
6639
+ return addFunctionImport({
6640
+ context: context,
6641
+ fixer: fixer,
6642
+ functions: ["useTranslation"],
6643
+ importPattern: REACT_I18_IMPORT_PATTERN
6644
+ });
6645
+ };
6566
6646
  var insertTextAfterPosition = function insertTextAfterPosition(position, inputString, textToInsert) {
6567
6647
  var firstCharacter = inputString.charAt(position);
6568
6648
  var restOfString = inputString.slice(position + 1);
6569
6649
  return firstCharacter + textToInsert + restOfString;
6570
6650
  };
6651
+ var reportError = function reportError(_ref) {
6652
+ var context = _ref.context,
6653
+ node = _ref.node,
6654
+ arrowFunctionExpression = _ref.arrowFunctionExpression,
6655
+ _ref$isExportStatemen = _ref.isExportStatement,
6656
+ isExportStatement = _ref$isExportStatemen === void 0 ? false : _ref$isExportStatemen;
6657
+ return context.report({
6658
+ node: node,
6659
+ message: NO_WITH_T_IN_SMART_COMPONENTS,
6660
+ fix: function fix(fixer) {
6661
+ var fixers = [];
6662
+ var replacedCodeWithUseTranslation = getCodeWithUseTranslationHook(context, arrowFunctionExpression);
6663
+ if (isExportStatement) {
6664
+ fixers.push(fixer.replaceText(node.declaration, node.declaration.arguments[0].name));
6665
+ fixers.push(fixer.replaceText(arrowFunctionExpression, replacedCodeWithUseTranslation));
6666
+ } else {
6667
+ fixers.push(fixer.replaceText(node.declarations[0].init, replacedCodeWithUseTranslation));
6668
+ }
6669
+ var importUseTranslation = createUseTranslationImport(context, fixer);
6670
+ importUseTranslation && fixers.push(importUseTranslation);
6671
+ return fixers;
6672
+ }
6673
+ });
6674
+ };
6571
6675
 
6572
6676
  var noWithTForSmartComponents = {
6573
6677
  meta: {
@@ -6579,52 +6683,26 @@
6579
6683
  fixable: "code"
6580
6684
  },
6581
6685
  create: function create(context) {
6686
+ var componentDeclaration = null;
6582
6687
  return {
6583
6688
  VariableDeclaration: function VariableDeclaration(node) {
6689
+ componentDeclaration = node;
6584
6690
  if (!pure.matches(WITH_T_HOC_PATTERN, node)) return;
6585
6691
  var arrowFunctionExpression = node.declarations[0].init.arguments[0];
6586
- var body = arrowFunctionExpression.body;
6587
- context.report({
6692
+ reportError({
6693
+ context: context,
6588
6694
  node: node,
6589
- message: NO_WITH_T_IN_SMART_COMPONENTS,
6590
- fix: function fix(fixer) {
6591
- var fixers = [];
6592
- var _arrowFunctionExpress = _toArray(arrowFunctionExpression.params),
6593
- props = _arrowFunctionExpress[0],
6594
- restParams = _arrowFunctionExpress.slice(1);
6595
- var getPropsCode = function getPropsCode() {
6596
- if (ramda.isEmpty(arrowFunctionExpression.params)) return "";
6597
- if (props.type === TYPES.IDENTIFIER) {
6598
- return "{...".concat(getCode$1(context, props), " }");
6599
- }
6600
- if (props.type === TYPES.OBJECT_PATTERN) {
6601
- var _props$properties, _props$properties2, _props$properties2$0$;
6602
- if (((_props$properties = props.properties) === null || _props$properties === void 0 ? void 0 : _props$properties.length) === 1 && ((_props$properties2 = props.properties) === null || _props$properties2 === void 0 ? void 0 : (_props$properties2$0$ = _props$properties2[0].value) === null || _props$properties2$0$ === void 0 ? void 0 : _props$properties2$0$.name) === "t") {
6603
- return "";
6604
- }
6605
- return "{".concat(props.properties.map(function (property) {
6606
- return getCode$1(context, property);
6607
- }).filter(pure.isNot("t")).join(", "), " }");
6608
- }
6609
- return "";
6610
- };
6611
- var codeInsideBody = getCode$1(context, body);
6612
- var codeWithUseTranslation = insertTextAfterPosition(0, codeInsideBody, "const { t } = useTranslation();\n");
6613
- var updatedProps = getPropsCode();
6614
- var replacedCodeWithUseTranslation = "(".concat(updatedProps).concat(ramda.isEmpty(restParams) ? "" : "".concat(pure.isNotEmpty(updatedProps) ? ", " : "").concat(restParams.map(function (param) {
6615
- return getCode$1(context, param);
6616
- }).join(", ")), ") => ").concat(codeWithUseTranslation);
6617
- var replaceIncorrectWithTCode = fixer.replaceText(node.declarations[0].init, replacedCodeWithUseTranslation);
6618
- fixers.push(replaceIncorrectWithTCode);
6619
- var importUseTranslation = addFunctionImport({
6620
- context: context,
6621
- fixer: fixer,
6622
- functions: ["useTranslation"],
6623
- importPattern: REACT_I18_IMPORT_PATTERN
6624
- });
6625
- importUseTranslation && fixers.push(importUseTranslation);
6626
- return fixers;
6627
- }
6695
+ arrowFunctionExpression: arrowFunctionExpression
6696
+ });
6697
+ },
6698
+ ExportDefaultDeclaration: function ExportDefaultDeclaration(node) {
6699
+ if (!pure.matches(EXPORTED_WITH_T_PATTERN, node)) return;
6700
+ if (!pure.matches(SMART_COMPONENT_PATTERN, componentDeclaration)) return;
6701
+ reportError({
6702
+ context: context,
6703
+ node: node,
6704
+ arrowFunctionExpression: componentDeclaration.declarations[0].init,
6705
+ isExportStatement: true
6628
6706
  });
6629
6707
  }
6630
6708
  };
@@ -6803,6 +6881,13 @@
6803
6881
  array.splice(index, 1);
6804
6882
  }
6805
6883
  };
6884
+ var findIndexToInsert = function findIndexToInsert(endIndex, attributes) {
6885
+ var index = endIndex - 1;
6886
+ for (; index >= 0; --index) {
6887
+ if (attributes[index].type === TYPES.JSX_SPREAD_ATTRIBUTE) return index + 1;
6888
+ }
6889
+ return index + 1;
6890
+ };
6806
6891
 
6807
6892
  var mergeSpreadAttributes = {
6808
6893
  meta: {
@@ -6928,6 +7013,43 @@
6928
7013
  }
6929
7014
  };
6930
7015
 
7016
+ var moveSpreadAttributesToTopPosition = {
7017
+ meta: {
7018
+ type: "problem",
7019
+ docs: {
7020
+ url: "https://github.com/bigbinary/eslint-plugin-neeto/blob/main/docs/src/rules/move-spread-attributes-to-top-position.md",
7021
+ description: "Enforce moving spread attributes to top most position in oprning elements"
7022
+ },
7023
+ fixable: "code"
7024
+ },
7025
+ create: function create(context) {
7026
+ return {
7027
+ JSXSpreadAttribute: function JSXSpreadAttribute(node) {
7028
+ var _node$argument$proper;
7029
+ if (!pure.matches(SPREAD_ATTRIBUTE_WITH_OBJECT_EXPRESSION, node) || (_node$argument$proper = node.argument.properties) !== null && _node$argument$proper !== void 0 && _node$argument$proper.find(pure.matches(OTHER_PROPS_INSIDE_SPREAD_ATTRIBUTE))) {
7030
+ return;
7031
+ }
7032
+ var attributes = node.parent.attributes;
7033
+ var nodeIndex = pure.findIndexBy({
7034
+ range: node.range
7035
+ }, attributes);
7036
+ var indexToInsert = findIndexToInsert(nodeIndex, attributes);
7037
+ if (indexToInsert === nodeIndex) return;
7038
+ var indentLevel = context.getSourceCode().getFirstToken(attributes[0]).loc.start.column;
7039
+ context.report({
7040
+ node: node,
7041
+ message: MOVE_SPREAD_ATTRIBUTES_TO_TOP,
7042
+ fix: function fix(fixer) {
7043
+ var removeNode = fixer.remove(node);
7044
+ var moveNode = fixer.insertTextBefore(attributes[indexToInsert], "".concat(context.getSourceCode().getText(node), "\n").concat(" ".repeat(indentLevel)));
7045
+ return [moveNode, removeNode];
7046
+ }
7047
+ });
7048
+ }
7049
+ };
7050
+ }
7051
+ };
7052
+
6931
7053
  var noRepetitionInPropKeyAndValueName = {
6932
7054
  meta: {
6933
7055
  type: "problem",
@@ -26825,7 +26947,8 @@
26825
26947
  "no-unnecessary-if-condition": noUnnecessaryIfCondition,
26826
26948
  "zustand-use-with-immutable-actions-wrapper-inside-create": useWithImmutableActionsWrapperInsideCreate,
26827
26949
  "add-required-peer-dependencies": addRequiredPeerDependencies,
26828
- "use-common-constants": useCommonConstants
26950
+ "use-common-constants": useCommonConstants,
26951
+ "move-spread-attributes-to-top-position": moveSpreadAttributesToTopPosition
26829
26952
  },
26830
26953
  configs: {
26831
26954
  recommended: recommended,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigbinary/eslint-plugin-neeto",
3
- "version": "1.1.19",
3
+ "version": "1.1.21",
4
4
  "main": "dist/index.js",
5
5
  "license": "UNLICENSED",
6
6
  "scripts": {