eslint-plugin-nextfriday 5.0.0 → 5.0.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,11 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 5.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#138](https://github.com/next-friday/eslint-plugin-nextfriday/pull/138) [`28c600d`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/28c600d4746de76f7587e2fb5eab97ec5bdc6658) Thanks [@joetakara](https://github.com/joetakara)! - fix `no-inline-nested-object` scope — the rule now applies only to function-like contexts (call arguments, `new` expressions, `return` statements, arrow implicit returns, and JSX expressions) instead of every object property; module-level data declarations such as route tables, dependency rule arrays, and configuration objects are no longer flagged, eliminating false positives in patterns where Prettier already controls the layout
8
+
3
9
  ## 5.0.0
4
10
 
5
11
  ### Major Changes
@@ -1,96 +1,96 @@
1
1
  # no-inline-nested-object
2
2
 
3
- Require object or array values that contain further nested objects or arrays to span multiple lines.
3
+ Require object or array values passed to functions, returned from functions, or used as JSX attributes to span multiple lines when they contain nested objects or arrays.
4
+
5
+ > This rule is auto-fixable using `--fix`.
4
6
 
5
7
  ## Rule Details
6
8
 
7
- This rule enforces that when an object property's value is itself an object or array **that contains further nested structures inside**, it must span multiple lines. Flat collections — objects of primitive properties or arrays of simple references — are allowed inline because Prettier already controls their wrapping via `printWidth`.
9
+ This rule applies **only to function-like contexts**:
10
+
11
+ - Arguments to function calls (`CallExpression`) and constructor calls (`NewExpression`)
12
+ - Values returned from functions (`return` statements)
13
+ - Implicit returns from arrow functions
14
+ - Expressions inside JSX braces (props, children)
15
+
16
+ When the value passed/returned in one of those contexts is an inline object or array that contains another object or array as a property value or element, the rule requires it to span multiple lines. Flat collections — objects of primitive properties or arrays of simple references — are allowed inline because Prettier already controls their wrapping via `printWidth`.
8
17
 
9
- A "nested structure" is any object or array element/property whose value is another object or array. The rule deliberately ignores depth-1 collections so it does not fight Prettier on simple data and configuration tables.
18
+ The rule deliberately **does not apply to module-level data declarations** (e.g., `const config = { ... }`, route tables, dependency rule arrays). These are static configuration data, not function calls — Prettier handles their layout, and forcing them multiline produces noisy diffs without aiding readability.
10
19
 
11
20
  ### Why?
12
21
 
13
- Truly nested structures are easy to misread when collapsed onto a single line, and adding or removing an inner element produces noisy diffs. Flat collections do not have the same problem and are best left to Prettier's line-length logic.
22
+ Truly nested structures passed at a call site are easy to misread when collapsed onto a single line, and adding or removing an inner element produces noisy diffs at the call site. The rule does not target data declarations because forcing static configuration arrays/objects onto multiple lines fights Prettier and bloats config files without aiding readability.
14
23
 
15
24
  ## Examples
16
25
 
17
26
  ### Incorrect
18
27
 
19
- <!-- prettier-ignore -->
20
28
  ```ts
21
- const obj = {
22
- items: [{ a: 1 }, { b: 2 }],
23
- };
29
+ useState({ a: { b: 1 } });
24
30
  ```
25
31
 
26
- <!-- prettier-ignore -->
27
32
  ```ts
28
- const obj = {
29
- matrix: [[1, 2], [3, 4]],
30
- };
33
+ doThing([{ a: 1 }, { b: 2 }]);
31
34
  ```
32
35
 
33
36
  ```ts
34
- const obj = {
35
- layer: { inner: { leaf: 1 } },
36
- };
37
+ function build() {
38
+ return { user: { id: 1 } };
39
+ }
37
40
  ```
38
41
 
39
42
  ```ts
40
- const obj = {
41
- wrap: { items: [1, 2, 3] },
42
- };
43
+ const factory = () => ({ a: { b: 1 } });
44
+ ```
45
+
46
+ ```tsx
47
+ const el = <Comp prop={{ a: { b: 1 } }} />;
43
48
  ```
44
49
 
45
50
  ### Correct
46
51
 
47
- <!-- prettier-ignore -->
52
+ Function-context calls expanded onto multiple lines:
53
+
48
54
  ```ts
49
- const obj = {
50
- items: [
51
- { a: 1 },
52
- { b: 2 },
53
- ],
54
- };
55
+ useState({
56
+ a: { b: 1 },
57
+ });
55
58
  ```
56
59
 
57
60
  ```ts
58
- const obj = {
59
- layer: {
60
- inner: { leaf: 1 },
61
- },
62
- };
61
+ doThing([{ a: 1 }, { b: 2 }]);
63
62
  ```
64
63
 
65
- Flat values stay inline:
66
-
67
64
  ```ts
68
- const obj = {
69
- config: { enabled: true, timeout: 5000 },
70
- database: { host: "localhost", port: 5432, name: "myapp" },
71
- };
65
+ function build() {
66
+ return {
67
+ user: { id: 1 },
68
+ };
69
+ }
72
70
  ```
73
71
 
72
+ Flat values stay inline:
73
+
74
74
  ```ts
75
- const obj = {
76
- options: ["primary", "foreground", "danger", "outline", "ghost", "link"],
77
- allow: [target.utils, target.types, target.constants],
78
- };
75
+ useState({ enabled: true, timeout: 5000 });
76
+ useState([1, 2, 3]);
79
77
  ```
80
78
 
81
- Empty nested objects and arrays are allowed inline:
79
+ Module-level data declarations are not checked:
82
80
 
81
+ <!-- prettier-ignore -->
83
82
  ```ts
84
- const initialState = {
85
- data: {},
86
- errors: [],
83
+ const dependencyRules = [
84
+ { from: source.modules, allow: [{ to: { type: "templates" } }] },
85
+ ];
86
+
87
+ const obj = {
88
+ items: [{ a: 1 }, { b: 2 }],
89
+ matrix: [[1, 2], [3, 4]],
90
+ layer: { inner: { leaf: 1 } },
87
91
  };
88
92
  ```
89
93
 
90
94
  ## When Not To Use It
91
95
 
92
- If your team prefers compact single-line nested structures regardless of depth, or if your project has different formatting preferences.
93
-
94
- ## Fixable
95
-
96
- This rule is auto-fixable. Running ESLint with the `--fix` flag will expand inline collections that contain nested structures onto multiple lines.
96
+ If your team prefers compact single-line nested structures at call sites regardless of nesting, or if your project has different formatting preferences.
package/lib/index.cjs CHANGED
@@ -32,7 +32,7 @@ let emoji_regex = require("emoji-regex");
32
32
  emoji_regex = __toESM(emoji_regex, 1);
33
33
  //#region package.json
34
34
  var name = "eslint-plugin-nextfriday";
35
- var version = "5.0.0";
35
+ var version = "5.0.1";
36
36
  //#endregion
37
37
  //#region src/rules/boolean-naming-prefix.ts
38
38
  const createRule$26 = _typescript_eslint_utils.ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
@@ -1778,9 +1778,6 @@ const noHelperFunctionInTest = _typescript_eslint_utils.ESLintUtils.RuleCreator(
1778
1778
  //#endregion
1779
1779
  //#region src/rules/no-inline-nested-object.ts
1780
1780
  const createRule$11 = _typescript_eslint_utils.ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1781
- function isObjectOrArray(node) {
1782
- return node.type === _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression || node.type === _typescript_eslint_utils.AST_NODE_TYPES.ArrayExpression || node.type === _typescript_eslint_utils.AST_NODE_TYPES.TSAsExpression;
1783
- }
1784
1781
  function getInnerExpression(node) {
1785
1782
  if (node.type === _typescript_eslint_utils.AST_NODE_TYPES.TSAsExpression) return getInnerExpression(node.expression);
1786
1783
  return node;
@@ -1803,7 +1800,7 @@ const noInlineNestedObject = createRule$11({
1803
1800
  name: "no-inline-nested-object",
1804
1801
  meta: {
1805
1802
  type: "layout",
1806
- docs: { description: "Require object or array values that contain further nested objects or arrays to span multiple lines" },
1803
+ docs: { description: "Require object or array values passed to functions, returned, or used as JSX attributes to span multiple lines when they contain nested objects or arrays" },
1807
1804
  fixable: "whitespace",
1808
1805
  messages: { requireMultiline: "Inline collections containing nested objects or arrays should span multiple lines" },
1809
1806
  schema: []
@@ -1811,32 +1808,54 @@ const noInlineNestedObject = createRule$11({
1811
1808
  defaultOptions: [],
1812
1809
  create(context) {
1813
1810
  const { sourceCode } = context;
1814
- return { Property(node) {
1815
- if (!node.value || !isObjectOrArray(node.value)) return;
1816
- const valueNode = getInnerExpression(node.value);
1817
- if (valueNode.type !== _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression && valueNode.type !== _typescript_eslint_utils.AST_NODE_TYPES.ArrayExpression) return;
1818
- if (!valueNode.loc) return;
1819
- if (valueNode.loc.start.line !== valueNode.loc.end.line) return;
1820
- if (!containsNestedStructure(valueNode)) return;
1821
- const elements = valueNode.type === _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression ? valueNode.properties : valueNode.elements;
1811
+ function checkValue(node) {
1812
+ if (!node) return;
1813
+ const inner = getInnerExpression(node);
1814
+ if (inner.type !== _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression && inner.type !== _typescript_eslint_utils.AST_NODE_TYPES.ArrayExpression) return;
1815
+ if (!inner.loc) return;
1816
+ if (inner.loc.start.line !== inner.loc.end.line) return;
1817
+ if (!containsNestedStructure(inner)) return;
1818
+ const elements = inner.type === _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression ? inner.properties : inner.elements;
1822
1819
  context.report({
1823
- node: valueNode,
1820
+ node: inner,
1824
1821
  messageId: "requireMultiline",
1825
1822
  fix(fixer) {
1826
- const openBrace = sourceCode.getFirstToken(valueNode);
1827
- const closeBrace = sourceCode.getLastToken(valueNode);
1828
- if (!openBrace || !closeBrace) return null;
1829
- const indent = " ".repeat(node.loc?.start.column ?? 0);
1830
- const innerIndent = `${indent} `;
1823
+ const lineIndentMatch = (sourceCode.lines[inner.loc.start.line - 1] ?? "").match(/^(\s*)/);
1824
+ const lineIndent = lineIndentMatch ? lineIndentMatch[1] : "";
1825
+ const innerIndent = `${lineIndent} `;
1831
1826
  const elementTexts = elements.filter((el) => el !== null).map((el) => sourceCode.getText(el));
1832
- const isObject = valueNode.type === _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression;
1827
+ const isObject = inner.type === _typescript_eslint_utils.AST_NODE_TYPES.ObjectExpression;
1833
1828
  const openChar = isObject ? "{" : "[";
1834
1829
  const closeChar = isObject ? "}" : "]";
1835
- const newContent = `${openChar}\n${elementTexts.map((text) => `${innerIndent}${text},`).join("\n")}\n${indent}${closeChar}`;
1836
- return fixer.replaceText(valueNode, newContent);
1830
+ const newContent = `${openChar}\n${elementTexts.map((text) => `${innerIndent}${text},`).join("\n")}\n${lineIndent}${closeChar}`;
1831
+ return fixer.replaceText(inner, newContent);
1837
1832
  }
1838
1833
  });
1839
- } };
1834
+ }
1835
+ function checkArguments(args) {
1836
+ args.forEach((arg) => {
1837
+ if (arg.type === _typescript_eslint_utils.AST_NODE_TYPES.SpreadElement) return;
1838
+ checkValue(arg);
1839
+ });
1840
+ }
1841
+ return {
1842
+ CallExpression(node) {
1843
+ checkArguments(node.arguments);
1844
+ },
1845
+ NewExpression(node) {
1846
+ checkArguments(node.arguments);
1847
+ },
1848
+ ReturnStatement(node) {
1849
+ checkValue(node.argument);
1850
+ },
1851
+ ArrowFunctionExpression(node) {
1852
+ if (node.body.type !== _typescript_eslint_utils.AST_NODE_TYPES.BlockStatement) checkValue(node.body);
1853
+ },
1854
+ JSXExpressionContainer(node) {
1855
+ if (node.expression.type === _typescript_eslint_utils.AST_NODE_TYPES.JSXEmptyExpression) return;
1856
+ checkValue(node.expression);
1857
+ }
1858
+ };
1840
1859
  }
1841
1860
  });
1842
1861
  //#endregion