eslint-plugin-nextfriday 5.0.0 → 5.0.2

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/lib/index.js CHANGED
@@ -4,7 +4,7 @@ import path from "path";
4
4
  import emojiRegex from "emoji-regex";
5
5
  //#region package.json
6
6
  var name = "eslint-plugin-nextfriday";
7
- var version = "5.0.0";
7
+ var version = "5.0.2";
8
8
  //#endregion
9
9
  //#region src/rules/boolean-naming-prefix.ts
10
10
  const createRule$26 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
@@ -134,10 +134,15 @@ const SCREAMING_SNAKE_CASE_REGEX$1 = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$/;
134
134
  const SNAKE_CASE_REGEX = /^[a-z]+_[a-z0-9_]*$/;
135
135
  const toScreamingSnakeCase = (str) => str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toUpperCase();
136
136
  const isMagicLiteral = (init) => {
137
- if (init.type === AST_NODE_TYPES.Literal) return typeof init.value === "string" || typeof init.value === "number";
137
+ if (init.type === AST_NODE_TYPES.Literal) return typeof init.value === "string" || typeof init.value === "number" || typeof init.value === "bigint" || "regex" in init;
138
138
  if (init.type === AST_NODE_TYPES.UnaryExpression) {
139
139
  const { argument, operator } = init;
140
- return (operator === "-" || operator === "+") && argument.type === AST_NODE_TYPES.Literal && typeof argument.value === "number";
140
+ if (operator !== "-" && operator !== "+") return false;
141
+ return argument.type === AST_NODE_TYPES.Literal && (typeof argument.value === "number" || typeof argument.value === "bigint");
142
+ }
143
+ if (init.type === AST_NODE_TYPES.NewExpression) {
144
+ if (init.callee.type !== AST_NODE_TYPES.Identifier || init.callee.name !== "RegExp") return false;
145
+ return init.arguments.every((arg) => arg.type === AST_NODE_TYPES.Literal && typeof arg.value === "string");
141
146
  }
142
147
  return false;
143
148
  };
@@ -151,7 +156,7 @@ const enforceConstantCase = createRule$25({
151
156
  name: "enforce-constant-case",
152
157
  meta: {
153
158
  type: "suggestion",
154
- docs: { description: "Enforce SCREAMING_SNAKE_CASE for global magic-number and magic-text constants" },
159
+ docs: { description: "Enforce SCREAMING_SNAKE_CASE for global magic-number, magic-text, bigint, and RegExp constants" },
155
160
  messages: {
156
161
  useScreamingSnakeCase: "Constant '{{ name }}' should use SCREAMING_SNAKE_CASE. Rename to '{{ suggestion }}'.",
157
162
  noSnakeCase: "Global constant '{{ name }}' should not use snake_case. Rename to '{{ suggestion }}'."
@@ -1750,9 +1755,6 @@ const noHelperFunctionInTest = ESLintUtils.RuleCreator((name) => `https://github
1750
1755
  //#endregion
1751
1756
  //#region src/rules/no-inline-nested-object.ts
1752
1757
  const createRule$11 = ESLintUtils.RuleCreator((name) => `https://github.com/next-friday/eslint-plugin-nextfriday/blob/main/docs/rules/${name.replaceAll("-", "_").toUpperCase()}.md`);
1753
- function isObjectOrArray(node) {
1754
- return node.type === AST_NODE_TYPES.ObjectExpression || node.type === AST_NODE_TYPES.ArrayExpression || node.type === AST_NODE_TYPES.TSAsExpression;
1755
- }
1756
1758
  function getInnerExpression(node) {
1757
1759
  if (node.type === AST_NODE_TYPES.TSAsExpression) return getInnerExpression(node.expression);
1758
1760
  return node;
@@ -1775,7 +1777,7 @@ const noInlineNestedObject = createRule$11({
1775
1777
  name: "no-inline-nested-object",
1776
1778
  meta: {
1777
1779
  type: "layout",
1778
- docs: { description: "Require object or array values that contain further nested objects or arrays to span multiple lines" },
1780
+ 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" },
1779
1781
  fixable: "whitespace",
1780
1782
  messages: { requireMultiline: "Inline collections containing nested objects or arrays should span multiple lines" },
1781
1783
  schema: []
@@ -1783,32 +1785,54 @@ const noInlineNestedObject = createRule$11({
1783
1785
  defaultOptions: [],
1784
1786
  create(context) {
1785
1787
  const { sourceCode } = context;
1786
- return { Property(node) {
1787
- if (!node.value || !isObjectOrArray(node.value)) return;
1788
- const valueNode = getInnerExpression(node.value);
1789
- if (valueNode.type !== AST_NODE_TYPES.ObjectExpression && valueNode.type !== AST_NODE_TYPES.ArrayExpression) return;
1790
- if (!valueNode.loc) return;
1791
- if (valueNode.loc.start.line !== valueNode.loc.end.line) return;
1792
- if (!containsNestedStructure(valueNode)) return;
1793
- const elements = valueNode.type === AST_NODE_TYPES.ObjectExpression ? valueNode.properties : valueNode.elements;
1788
+ function checkValue(node) {
1789
+ if (!node) return;
1790
+ const inner = getInnerExpression(node);
1791
+ if (inner.type !== AST_NODE_TYPES.ObjectExpression && inner.type !== AST_NODE_TYPES.ArrayExpression) return;
1792
+ if (!inner.loc) return;
1793
+ if (inner.loc.start.line !== inner.loc.end.line) return;
1794
+ if (!containsNestedStructure(inner)) return;
1795
+ const elements = inner.type === AST_NODE_TYPES.ObjectExpression ? inner.properties : inner.elements;
1794
1796
  context.report({
1795
- node: valueNode,
1797
+ node: inner,
1796
1798
  messageId: "requireMultiline",
1797
1799
  fix(fixer) {
1798
- const openBrace = sourceCode.getFirstToken(valueNode);
1799
- const closeBrace = sourceCode.getLastToken(valueNode);
1800
- if (!openBrace || !closeBrace) return null;
1801
- const indent = " ".repeat(node.loc?.start.column ?? 0);
1802
- const innerIndent = `${indent} `;
1800
+ const lineIndentMatch = (sourceCode.lines[inner.loc.start.line - 1] ?? "").match(/^(\s*)/);
1801
+ const lineIndent = lineIndentMatch ? lineIndentMatch[1] : "";
1802
+ const innerIndent = `${lineIndent} `;
1803
1803
  const elementTexts = elements.filter((el) => el !== null).map((el) => sourceCode.getText(el));
1804
- const isObject = valueNode.type === AST_NODE_TYPES.ObjectExpression;
1804
+ const isObject = inner.type === AST_NODE_TYPES.ObjectExpression;
1805
1805
  const openChar = isObject ? "{" : "[";
1806
1806
  const closeChar = isObject ? "}" : "]";
1807
- const newContent = `${openChar}\n${elementTexts.map((text) => `${innerIndent}${text},`).join("\n")}\n${indent}${closeChar}`;
1808
- return fixer.replaceText(valueNode, newContent);
1807
+ const newContent = `${openChar}\n${elementTexts.map((text) => `${innerIndent}${text},`).join("\n")}\n${lineIndent}${closeChar}`;
1808
+ return fixer.replaceText(inner, newContent);
1809
1809
  }
1810
1810
  });
1811
- } };
1811
+ }
1812
+ function checkArguments(args) {
1813
+ args.forEach((arg) => {
1814
+ if (arg.type === AST_NODE_TYPES.SpreadElement) return;
1815
+ checkValue(arg);
1816
+ });
1817
+ }
1818
+ return {
1819
+ CallExpression(node) {
1820
+ checkArguments(node.arguments);
1821
+ },
1822
+ NewExpression(node) {
1823
+ checkArguments(node.arguments);
1824
+ },
1825
+ ReturnStatement(node) {
1826
+ checkValue(node.argument);
1827
+ },
1828
+ ArrowFunctionExpression(node) {
1829
+ if (node.body.type !== AST_NODE_TYPES.BlockStatement) checkValue(node.body);
1830
+ },
1831
+ JSXExpressionContainer(node) {
1832
+ if (node.expression.type === AST_NODE_TYPES.JSXEmptyExpression) return;
1833
+ checkValue(node.expression);
1834
+ }
1835
+ };
1812
1836
  }
1813
1837
  });
1814
1838
  //#endregion