@zayne-labs/eslint-config 0.13.13 → 0.13.15

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.
@@ -29,15 +29,12 @@ const jsxShorthandBoolean = () => (context) => {
29
29
  node
30
30
  });
31
31
  break;
32
- case policy === "never" && value == null:
33
- context.report({
34
- data: { message: `Set attribute value for '${propName}'.` },
35
- fix: (fixer) => fixer.insertTextAfter(node.name, `={true}`),
36
- messageId: "default",
37
- node: node.value ?? node
38
- });
39
- break;
40
- default: break;
32
+ case policy === "never" && value == null: context.report({
33
+ data: { message: `Set attribute value for '${propName}'.` },
34
+ fix: (fixer) => fixer.insertTextAfter(node.name, "={true}"),
35
+ messageId: "default",
36
+ node: node.value ?? node
37
+ });
41
38
  }
42
39
  } };
43
40
  };
@@ -60,10 +57,7 @@ const jsxShorthandFragment = () => (context, toolkit) => {
60
57
  switch (context.options[0] ?? "always") {
61
58
  case "always": return { JSXElement: (node) => {
62
59
  if (node.openingElement.attributes.length > 0) return;
63
- const name = stringifyJsx(node.openingElement.name);
64
- const isFragmentNode = name === "Fragment" || name === "React.Fragment";
65
- const variableToCheck = name.split(".")[0] ?? name;
66
- if (!(isFragmentNode && toolkit.is.APIFromReact(variableToCheck, context.sourceCode.getScope(node.openingElement)))) return;
60
+ if (!toolkit.is.API("Fragment")(node.openingElement.name)) return;
67
61
  context.report({
68
62
  data: { message: "Use fragment shorthand syntax instead of 'Fragment' component." },
69
63
  fix: (fixer) => {
@@ -106,4 +100,4 @@ const getCustomJsxPlugin = () => {
106
100
  //#endregion
107
101
  export { getCustomJsxPlugin };
108
102
 
109
- //# sourceMappingURL=jsxRules-BAjKnxGs.js.map
103
+ //# sourceMappingURL=jsxRules-DR1G9lbZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsxRules-DR1G9lbZ.js","names":[],"sources":["../src/rules/react/utils.ts","../src/rules/react/jsxRules.ts"],"sourcesContent":["/* eslint-disable ts-eslint/no-unsafe-enum-comparison -- Ignore, I don't want the enum to be bundled */\nimport type { TSESTree } from \"@typescript-eslint/types\";\n\nexport const stringifyJsx = (\n\tnode:\n\t\t| TSESTree.JSXClosingElement\n\t\t| TSESTree.JSXClosingFragment\n\t\t| TSESTree.JSXIdentifier\n\t\t| TSESTree.JSXMemberExpression\n\t\t| TSESTree.JSXNamespacedName\n\t\t| TSESTree.JSXOpeningElement\n\t\t| TSESTree.JSXOpeningFragment\n\t\t| TSESTree.JSXText\n): string => {\n\tswitch (node.type) {\n\t\tcase \"JSXClosingElement\": {\n\t\t\t// Closing tags like \"</div>\"\n\t\t\treturn `</${stringifyJsx(node.name)}>`;\n\t\t}\n\t\tcase \"JSXClosingFragment\": {\n\t\t\t// Fragment closing syntax \"</>\"\n\t\t\treturn \"</>\";\n\t\t}\n\t\tcase \"JSXIdentifier\": {\n\t\t\t// Simple element names like \"div\" or component names like \"Button\"\n\t\t\treturn node.name;\n\t\t}\n\t\tcase \"JSXMemberExpression\": {\n\t\t\t// Dot-notation components like \"React.Fragment\" or \"Namespace.Component\"\n\t\t\treturn `${stringifyJsx(node.object)}.${stringifyJsx(node.property)}`;\n\t\t}\n\t\tcase \"JSXNamespacedName\": {\n\t\t\t// XML-style namespaced elements like \"svg:path\"\n\t\t\treturn `${node.namespace.name}:${node.name.name}`;\n\t\t}\n\t\tcase \"JSXOpeningElement\": {\n\t\t\t// Opening tags like \"<div>\"\n\t\t\treturn `<${stringifyJsx(node.name)}>`;\n\t\t}\n\t\tcase \"JSXOpeningFragment\": {\n\t\t\t// Fragment opening syntax \"<>\"\n\t\t\treturn \"<>\";\n\t\t}\n\t\tcase \"JSXText\": {\n\t\t\t// Text content inside JSX\n\t\t\treturn node.value;\n\t\t}\n\t\tdefault: {\n\t\t\treturn \"\";\n\t\t}\n\t}\n};\n","/* eslint-disable ts-eslint/no-unsafe-enum-comparison -- Ignore, I don't want the enum to be bundled */\n/* eslint-disable unicorn/consistent-function-scoping -- Ignore */\nimport eslintReactKit, { type RuleFunction } from \"@eslint-react/kit\";\nimport type { ESLintUtils } from \"@typescript-eslint/utils\";\nimport { stringifyJsx } from \"./utils\";\n\ntype OptionsShortHand = readonly [\"always\" | \"never\" | null];\n\ntype MessageID = \"default\";\ntype RuleWithMetaAndName = Omit<ESLintUtils.RuleWithMetaAndName<OptionsShortHand, MessageID>, \"create\">;\n\nconst jsxShorthandBoolean = (): RuleFunction => (context) => {\n\tconst policy: NonNullable<OptionsShortHand[0]> = (context.options[0] as OptionsShortHand[0]) ?? \"never\";\n\n\treturn {\n\t\tJSXAttribute: (node) => {\n\t\t\tconst { value } = node;\n\t\t\tconst propName = stringifyJsx(node.name);\n\n\t\t\tswitch (true) {\n\t\t\t\tcase policy === \"always\"\n\t\t\t\t\t&& value?.type === \"JSXExpressionContainer\"\n\t\t\t\t\t&& value.expression.type === \"Literal\"\n\t\t\t\t\t&& value.expression.value === true: {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: `Omit attribute value for '${propName}'.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => fixer.removeRange([node.name.range[1], value.range[1]]),\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t});\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase policy === \"never\" && value == null: {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: `Set attribute value for '${propName}'.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => fixer.insertTextAfter(node.name, \"={true}\"),\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode: node.value ?? node,\n\t\t\t\t\t});\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault: {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n};\n\nconst jsxShorthandBooleanMeta = {\n\tmeta: {\n\t\tdefaultOptions: [\"never\"],\n\t\tdocs: {\n\t\t\tdescription:\n\t\t\t\t\"Enforces whether to use shorthand syntax for boolean attributes (e.g., 'disabled') or not\",\n\t\t},\n\t\tfixable: \"code\",\n\t\thasSuggestions: true,\n\t\tmessages: {\n\t\t\tdefault: \"{{message}}\",\n\t\t},\n\t\tschema: [\n\t\t\t{\n\t\t\t\tenum: [\"always\", \"never\"],\n\t\t\t\ttype: \"string\",\n\t\t\t},\n\t\t],\n\t\ttype: \"suggestion\",\n\t},\n\tname: \"jsx-shorthand-boolean\",\n} as const satisfies RuleWithMetaAndName;\n\nconst jsxShorthandFragment = (): RuleFunction => (context, toolkit) => {\n\tconst policy: NonNullable<OptionsShortHand[0]> =\n\t\t(context.options[0] as OptionsShortHand[0]) ?? \"always\";\n\n\tswitch (policy) {\n\t\tcase \"always\": {\n\t\t\treturn {\n\t\t\t\tJSXElement: (node) => {\n\t\t\t\t\tif (node.openingElement.attributes.length > 0) return;\n\n\t\t\t\t\tconst isFragment = toolkit.is.API(\"Fragment\")(node.openingElement.name);\n\n\t\t\t\t\tif (!isFragment) return;\n\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: \"Use fragment shorthand syntax instead of 'Fragment' component.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => {\n\t\t\t\t\t\t\tif (node.closingElement == null) {\n\t\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.openingElement.range[0], node.openingElement.range[1]],\n\t\t\t\t\t\t\t\t\t\"<\"\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.closingElement.range[0], node.closingElement.range[1]],\n\t\t\t\t\t\t\t\t\t\"</>\"\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tcase \"never\": {\n\t\t\treturn {\n\t\t\t\tJSXFragment: (node) => {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: \"Use 'Fragment' component instead of fragment shorthand syntax.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => {\n\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.openingFragment.range[0], node.openingFragment.range[1]],\n\t\t\t\t\t\t\t\t\t`<Fragment>`\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.closingFragment.range[0], node.closingFragment.range[1]],\n\t\t\t\t\t\t\t\t\t`</Fragment>`\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tdefault: {\n\t\t\treturn {};\n\t\t}\n\t}\n};\n\nconst jsxShorthandFragmentMeta = {\n\tmeta: {\n\t\t...jsxShorthandBooleanMeta.meta,\n\t\tdefaultOptions: [\"always\"],\n\t\tdocs: {\n\t\t\tdescription: \"Enforces whether to use fragment shorthand syntax (<>...</>) or not\",\n\t\t},\n\t},\n\tname: \"jsx-shorthand-fragment\",\n} as const satisfies RuleWithMetaAndName;\n\nconst RuleMetaArray = [jsxShorthandBooleanMeta, jsxShorthandFragmentMeta];\n\nexport const getCustomJsxPlugin = () => {\n\tconst plugin = eslintReactKit().use(jsxShorthandBoolean).use(jsxShorthandFragment).getPlugin();\n\n\tfor (const ruleMeta of RuleMetaArray) {\n\t\tconst rule = plugin.rules?.[ruleMeta.name];\n\n\t\trule?.meta && Object.assign(rule.meta, ruleMeta.meta);\n\t}\n\n\treturn plugin;\n};\n"],"mappings":"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"}
package/dist/utils.d.ts CHANGED
@@ -1,14 +1,13 @@
1
- import { O as TypedFlatConfigItem } from "./index-B8a2EaF4.js";
1
+ import { O as TypedFlatConfigItem } from "./index-CH8E2ZDS.js";
2
2
  import { Awaitable } from "@zayne-labs/toolkit-type-helpers";
3
3
  import { ESLint } from "eslint";
4
-
5
4
  //#region src/utils.d.ts
6
- declare const isObject: <TObject extends object>(value: unknown) => value is TObject;
5
+ export declare const isObject: <TObject extends object>(value: unknown) => value is TObject;
7
6
  /**
8
7
  * @description - Combine array and non-array configs into a single array.
9
8
  */
10
- declare const combine: (...configs: Array<Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>>) => Promise<TypedFlatConfigItem[]>;
11
- declare const interopDefault: <TModule>(module: Awaitable<TModule>) => Promise<TModule extends {
9
+ export declare const combine: (...configs: Array<Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>>) => Promise<TypedFlatConfigItem[]>;
10
+ export declare const interopDefault: <TModule>(module: Awaitable<TModule>) => Promise<TModule extends {
12
11
  default: infer TDefaultExport;
13
12
  } ? TDefaultExport : TModule>;
14
13
  /**
@@ -29,8 +28,8 @@ declare const interopDefault: <TModule>(module: Awaitable<TModule>) => Promise<T
29
28
  * }]
30
29
  * ```
31
30
  */
32
- declare const renameRules: (rules: Record<string, unknown> | undefined, renameMap: Record<string, string>, separator?: string) => TypedFlatConfigItem["rules"] | undefined;
33
- declare const renamePlugins: (plugins: Record<string, unknown> | undefined, renameMap: Record<string, string>) => Record<string, ESLint.Plugin> | undefined;
31
+ export declare const renameRules: (rules: Record<string, unknown> | undefined, renameMap: Record<string, string>, separator?: string) => TypedFlatConfigItem["rules"] | undefined;
32
+ export declare const renamePlugins: (plugins: Record<string, unknown> | undefined, renameMap: Record<string, string>) => Record<string, ESLint.Plugin> | undefined;
34
33
  type OverrideConfigsOptions = {
35
34
  configArray: TypedFlatConfigItem[];
36
35
  overrides: TypedFlatConfigItem | ((config: TypedFlatConfigItem) => TypedFlatConfigItem);
@@ -69,7 +68,7 @@ type OverrideConfigsOptions = {
69
68
  * })
70
69
  * ```
71
70
  */
72
- declare const overrideConfigs: (options: OverrideConfigsOptions) => TypedFlatConfigItem[];
71
+ export declare const overrideConfigs: (options: OverrideConfigsOptions) => TypedFlatConfigItem[];
73
72
  type RenamePluginInConfigsOptions = {
74
73
  configArray: OverrideConfigsOptions["configArray"];
75
74
  overrides?: OverrideConfigsOptions["overrides"];
@@ -97,8 +96,8 @@ type RenamePluginInConfigsOptions = {
97
96
  * })
98
97
  * ```
99
98
  */
100
- declare const renamePluginInConfigs: (options: RenamePluginInConfigsOptions) => TypedFlatConfigItem[];
101
- declare const isPackageInScope: (name: string) => boolean;
99
+ export declare const renamePluginInConfigs: (options: RenamePluginInConfigsOptions) => TypedFlatConfigItem[];
100
+ export declare const isPackageInScope: (name: string) => boolean;
102
101
  /**
103
102
  * @description
104
103
  * - Ensures that packages are installed in the current scope.
@@ -108,9 +107,9 @@ declare const isPackageInScope: (name: string) => boolean;
108
107
  *
109
108
  * @param packages - The packages to ensure are installed.
110
109
  */
111
- declare const ensurePackages: (packages: Array<string | undefined>) => Promise<void>;
112
- declare const resolveOptions: <TObject>(option: boolean | TObject | undefined) => TObject;
113
- declare const parserPlain: {
110
+ export declare const ensurePackages: (packages: Array<string | undefined>) => Promise<void>;
111
+ export declare const resolveOptions: <TObject>(option: boolean | TObject | undefined) => TObject;
112
+ export declare const parserPlain: {
114
113
  meta: {
115
114
  name: string;
116
115
  };
@@ -135,8 +134,7 @@ declare const parserPlain: {
135
134
  };
136
135
  };
137
136
  };
138
- declare const isInEditorEnv: () => boolean;
139
- declare const isInGitHooksOrLintStaged: () => boolean;
137
+ export declare const isInEditorEnv: () => boolean;
138
+ export declare const isInGitHooksOrLintStaged: () => boolean;
140
139
  //#endregion
141
- export { combine, ensurePackages, interopDefault, isInEditorEnv, isInGitHooksOrLintStaged, isObject, isPackageInScope, overrideConfigs, parserPlain, renamePluginInConfigs, renamePlugins, renameRules, resolveOptions };
142
140
  //# sourceMappingURL=utils.d.ts.map
package/dist/utils.js CHANGED
@@ -50,7 +50,7 @@ const renameRules = (rules, renameMap, separator = "/") => {
50
50
  const renamePlugins = (plugins, renameMap) => {
51
51
  if (!plugins) return;
52
52
  const renamedPluginEntries = Object.entries(plugins).map(([pluginName, pluginValue]) => {
53
- if (pluginName in renameMap) return [renameMap[pluginName], pluginValue];
53
+ if (Object.hasOwn(renameMap, pluginName)) return [renameMap[pluginName], pluginValue];
54
54
  return [pluginName, pluginValue];
55
55
  });
56
56
  return Object.fromEntries(renamedPluginEntries);
@@ -152,7 +152,7 @@ const isPackageInScope = (name) => isPackageExists(name, { paths: [scopeUrl] });
152
152
  * @param packages - The packages to ensure are installed.
153
153
  */
154
154
  const ensurePackages = async (packages) => {
155
- if (process.env.CI || !process.stdout.isTTY || !isCwdInScope) return;
155
+ if (!isCwdInScope || process.env.CI || !process.stdout.isTTY) return;
156
156
  const nonExistingPackages = packages.filter((pkg) => pkg && !isPackageInScope(pkg));
157
157
  if (nonExistingPackages.length === 0) return;
158
158
  if (!await (await import("@clack/prompts")).confirm({ message: `${nonExistingPackages.length === 1 ? "Package" : "Packages"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install ${nonExistingPackages.length === 1 ? "it" : "them"}?` })) return;
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { isFunction, isObjectAndNotArray, type Awaitable } from \"@zayne-labs/toolkit-type-helpers\";\nimport type { ESLint } from \"eslint\";\nimport { isPackageExists } from \"local-pkg\";\nimport type { TypedFlatConfigItem } from \"./types\";\n\nexport const isObject = <TObject extends object>(value: unknown): value is TObject => {\n\treturn isObjectAndNotArray(value);\n};\n\n/**\n * @description - Combine array and non-array configs into a single array.\n */\nexport const combine = async (\n\t...configs: Array<Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>>\n): Promise<TypedFlatConfigItem[]> => {\n\t// eslint-disable-next-line ts-eslint/await-thenable -- False positive\n\tconst resolved = await Promise.all(configs);\n\n\treturn resolved.flat();\n};\n\nexport const interopDefault = async <TModule>(\n\tmodule: Awaitable<TModule>\n): Promise<TModule extends { default: infer TDefaultExport } ? TDefaultExport : TModule> => {\n\tconst resolved = await module;\n\n\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- casting is necessary to prevent assignability ts issues at call-site\n\treturn (resolved as { default: never }).default ?? resolved;\n};\n\n/**\n * @description - Rename plugin prefixes in a rule object.\n * Accepts a map of prefixes to rename.\n *\n * @example\n * ```ts\n * import { renameRules } from '@zayne-labs/eslint-config'\n *\n * export default [{\n * rules: renameRules(\n * {\n * '@typescript-eslint/indent': 'error'\n * },\n * { '@typescript-eslint': 'ts-eslint' }\n * )\n * }]\n * ```\n */\nexport const renameRules = (\n\trules: Record<string, unknown> | undefined,\n\trenameMap: Record<string, string>,\n\tseparator = \"/\"\n): TypedFlatConfigItem[\"rules\"] | undefined => {\n\tif (!rules) return;\n\n\tconst renamedRulesEntries = Object.entries(rules).map(([ruleName, ruleValue]) => {\n\t\tfor (const [oldRulePrefix, newRulePrefix] of Object.entries(renameMap)) {\n\t\t\tconst oldRulePrefixWithSeparator = `${oldRulePrefix}${separator}`;\n\n\t\t\tif (!ruleName.startsWith(oldRulePrefixWithSeparator)) continue;\n\n\t\t\tconst restOfRuleNameWithoutSeparator = ruleName.slice(oldRulePrefixWithSeparator.length);\n\n\t\t\t// == Skip if rule name still contains separator, which signifies a nested rule prefix that we don't want to rename\n\t\t\tif (restOfRuleNameWithoutSeparator.includes(separator)) continue;\n\n\t\t\tconst newRuleName = `${newRulePrefix}${separator}${restOfRuleNameWithoutSeparator}`;\n\n\t\t\treturn [newRuleName, ruleValue];\n\t\t}\n\n\t\treturn [ruleName, ruleValue];\n\t});\n\n\treturn Object.fromEntries(renamedRulesEntries) as TypedFlatConfigItem[\"rules\"];\n};\n\nexport const renamePlugins = (\n\tplugins: Record<string, unknown> | undefined,\n\trenameMap: Record<string, string>\n): Record<string, ESLint.Plugin> | undefined => {\n\tif (!plugins) return;\n\n\tconst renamedPluginEntries = Object.entries(plugins).map(([pluginName, pluginValue]) => {\n\t\tif (pluginName in renameMap) {\n\t\t\tconst newPluginName = renameMap[pluginName];\n\n\t\t\treturn [newPluginName, pluginValue];\n\t\t}\n\n\t\treturn [pluginName, pluginValue];\n\t});\n\n\treturn Object.fromEntries(renamedPluginEntries) as Record<string, ESLint.Plugin>;\n};\n\ntype OverrideConfigsOptions = {\n\tconfigArray: TypedFlatConfigItem[];\n\toverrides: TypedFlatConfigItem | ((config: TypedFlatConfigItem) => TypedFlatConfigItem);\n};\n\nconst getResolvedOverrides = (options: {\n\tconfigItem: TypedFlatConfigItem;\n\toverrides: OverrideConfigsOptions[\"overrides\"] | undefined;\n}) => {\n\tconst { configItem, overrides } = options;\n\n\treturn isFunction(overrides) ? overrides(configItem) : overrides;\n};\n\n/**\n * @description - Override configurations in a flat configs array with either a static config object or a function that returns a config object\n * @param options - Configuration options\n * @param options.configs - Array of flat config items to override\n * @param options.overrides - Either a config object to merge or a function that takes a config and returns overrides\n * @returns Array of merged config items with overrides applied\n *\n * @example\n * ```ts\n * import { overrideConfigs } from '@zayne-labs/eslint-config'\n *\n * // Override with static config\n * overrideConfigs({\n * configArray: existingConfigs,\n * overrides: {\n * rules: {\n * 'no-console': 'error'\n * }\n * }\n * })\n *\n * // Override with function\n * overrideConfigs({\n * configArray: existingConfigs,\n * overrides: (config) => ({\n * ...config,\n * rules: {\n * ...config.rules,\n * 'no-console': 'error'\n * }\n * })\n * })\n * ```\n */\nexport const overrideConfigs = (options: OverrideConfigsOptions): TypedFlatConfigItem[] => {\n\tconst { configArray, overrides } = options;\n\n\treturn configArray.map((configItem) => ({\n\t\t...configItem,\n\t\t...getResolvedOverrides({ configItem, overrides }),\n\t}));\n};\n\ntype RenamePluginInConfigsOptions = {\n\tconfigArray: OverrideConfigsOptions[\"configArray\"];\n\toverrides?: OverrideConfigsOptions[\"overrides\"];\n\trenameMap: Record<string, string>;\n};\n\n/**\n * @description - Rename plugin names and rules in a flat configs array\n *\n * @param options - Configuration options\n * @param options.configArray - Array of flat config items to process\n * @param options.overrides - Optional config overrides to apply\n * @param options.renameMap - Map of old plugin names to new names\n *\n * @example\n * ```ts\n * import { renamePluginInConfigs } from '@zayne-labs/eslint-config'\n * import someConfigs from './some-configs'\n *\n * renamePluginInConfigs({\n * configArray: someConfigs,\n * renameMap: {\n * '@typescript-eslint': 'ts-eslint',\n * 'import-x': 'import',\n * }\n * })\n * ```\n */\n\nexport const renamePluginInConfigs = (options: RenamePluginInConfigsOptions): TypedFlatConfigItem[] => {\n\tconst { configArray, overrides, renameMap } = options;\n\n\tconst renamedConfigs = overrideConfigs({\n\t\tconfigArray,\n\t\toverrides: (configItem) => ({\n\t\t\t...getResolvedOverrides({ configItem, overrides }),\n\n\t\t\t...(isObject(configItem.plugins) && {\n\t\t\t\tplugins: renamePlugins(configItem.plugins, renameMap),\n\t\t\t}),\n\t\t\t...(isObject(configItem.rules) && {\n\t\t\t\trules: renameRules(configItem.rules, renameMap),\n\t\t\t}),\n\t\t}),\n\t});\n\n\treturn renamedConfigs;\n};\n\nconst scopeUrl = fileURLToPath(new URL(\".\", import.meta.url));\nconst isCwdInScope = isPackageExists(\"@zayne-labs/eslint-config\");\n\nexport const isPackageInScope = (name: string): boolean => isPackageExists(name, { paths: [scopeUrl] });\n\n/**\n * @description\n * - Ensures that packages are installed in the current scope.\n * - If they are not installed, and the user is in a TTY, and the user is not in a CI environment,\n * and the user is in the same scope as this package, then prompt the user to\n * install the packages.\n *\n * @param packages - The packages to ensure are installed.\n */\nexport const ensurePackages = async (packages: Array<string | undefined>): Promise<void> => {\n\tif (process.env.CI || !process.stdout.isTTY || !isCwdInScope) return;\n\n\tconst nonExistingPackages = packages.filter((pkg) => pkg && !isPackageInScope(pkg));\n\n\tif (nonExistingPackages.length === 0) return;\n\n\tconst clackPrompt = await import(\"@clack/prompts\");\n\n\tconst result = await clackPrompt.confirm({\n\t\tmessage: `${nonExistingPackages.length === 1 ? \"Package\" : \"Packages\"} required for this config: ${nonExistingPackages.join(\", \")}. Do you want to install ${nonExistingPackages.length === 1 ? \"it\" : \"them\"}?`,\n\t});\n\n\tif (!result) return;\n\n\tconst antfuPkg = await import(\"@antfu/install-pkg\");\n\n\tawait antfuPkg.installPackage(nonExistingPackages as string[], { dev: true });\n};\n\nexport const resolveOptions = <TObject>(option: boolean | TObject | undefined) => {\n\treturn isObject(option) ? option : ({} as TObject);\n};\n\nexport const parserPlain = {\n\tmeta: {\n\t\tname: \"parser-plain\",\n\t},\n\tparseForESLint: (code: string) => ({\n\t\tast: {\n\t\t\tbody: [],\n\t\t\tcomments: [],\n\t\t\tloc: { end: code.length, start: 0 },\n\t\t\trange: [0, code.length],\n\t\t\ttokens: [],\n\t\t\ttype: \"Program\",\n\t\t},\n\t\tscopeManager: null,\n\t\tservices: { isPlain: true },\n\t\tvisitorKeys: {\n\t\t\tProgram: [],\n\t\t},\n\t}),\n};\n\nexport const isInEditorEnv = (): boolean => {\n\tif (process.env.CI) {\n\t\treturn false;\n\t}\n\n\tif (isInGitHooksOrLintStaged()) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tBoolean(process.env.VSCODE_PID)\n\t\t|| Boolean(process.env.VSCODE_CWD)\n\t\t|| Boolean(process.env.JETBRAINS_IDE)\n\t\t|| Boolean(process.env.VIM)\n\t\t|| Boolean(process.env.NVIM)\n\t\t|| (Boolean(process.env.ZED_ENVIRONMENT) && !process.env.ZED_TERM)\n\t);\n};\n\nexport const isInGitHooksOrLintStaged = (): boolean => {\n\treturn (\n\t\tBoolean(process.env.GIT_PARAMS)\n\t\t|| Boolean(process.env.VSCODE_GIT_COMMAND)\n\t\t|| Boolean(process.env.npm_lifecycle_script?.startsWith(\"lint-staged\"))\n\t);\n};\n"],"mappings":";;;;AAMA,MAAa,YAAoC,UAAqC;CACrF,OAAO,oBAAoB,KAAK;AACjC;;;;AAKA,MAAa,UAAU,OACtB,GAAG,YACiC;CAIpC,QAAO,MAFgB,QAAQ,IAAI,OAAO,GAE1B,KAAK;AACtB;AAEA,MAAa,iBAAiB,OAC7B,WAC2F;CAC3F,MAAM,WAAW,MAAM;CAGvB,OAAQ,SAAgC,WAAW;AACpD;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,eACZ,OACA,WACA,YAAY,QACkC;CAC9C,IAAI,CAAC,OAAO;CAEZ,MAAM,sBAAsB,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,UAAU,eAAe;EAChF,KAAK,MAAM,CAAC,eAAe,kBAAkB,OAAO,QAAQ,SAAS,GAAG;GACvE,MAAM,6BAA6B,GAAG,gBAAgB;GAEtD,IAAI,CAAC,SAAS,WAAW,0BAA0B,GAAG;GAEtD,MAAM,iCAAiC,SAAS,MAAM,2BAA2B,MAAM;GAGvF,IAAI,+BAA+B,SAAS,SAAS,GAAG;GAIxD,OAAO,CAAC,GAFe,gBAAgB,YAAY,kCAE9B,SAAS;EAC/B;EAEA,OAAO,CAAC,UAAU,SAAS;CAC5B,CAAC;CAED,OAAO,OAAO,YAAY,mBAAmB;AAC9C;AAEA,MAAa,iBACZ,SACA,cAC+C;CAC/C,IAAI,CAAC,SAAS;CAEd,MAAM,uBAAuB,OAAO,QAAQ,OAAO,EAAE,KAAK,CAAC,YAAY,iBAAiB;EACvF,IAAI,cAAc,WAGjB,OAAO,CAFe,UAAU,aAET,WAAW;EAGnC,OAAO,CAAC,YAAY,WAAW;CAChC,CAAC;CAED,OAAO,OAAO,YAAY,oBAAoB;AAC/C;AAOA,MAAM,wBAAwB,YAGxB;CACL,MAAM,EAAE,YAAY,cAAc;CAElC,OAAO,WAAW,SAAS,IAAI,UAAU,UAAU,IAAI;AACxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,mBAAmB,YAA2D;CAC1F,MAAM,EAAE,aAAa,cAAc;CAEnC,OAAO,YAAY,KAAK,gBAAgB;EACvC,GAAG;EACH,GAAG,qBAAqB;GAAE;GAAY;EAAU,CAAC;CAClD,EAAE;AACH;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,yBAAyB,YAAiE;CACtG,MAAM,EAAE,aAAa,WAAW,cAAc;CAgB9C,OAduB,gBAAgB;EACtC;EACA,YAAY,gBAAgB;GAC3B,GAAG,qBAAqB;IAAE;IAAY;GAAU,CAAC;GAEjD,GAAI,SAAS,WAAW,OAAO,KAAK,EACnC,SAAS,cAAc,WAAW,SAAS,SAAS,EACrD;GACA,GAAI,SAAS,WAAW,KAAK,KAAK,EACjC,OAAO,YAAY,WAAW,OAAO,SAAS,EAC/C;EACD;CACD,CAEoB;AACrB;AAEA,MAAM,WAAW,cAAc,IAAI,IAAI,KAAK,OAAO,KAAK,GAAG,CAAC;AAC5D,MAAM,eAAe,gBAAgB,2BAA2B;AAEhE,MAAa,oBAAoB,SAA0B,gBAAgB,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;;;;;;;;;;AAWtG,MAAa,iBAAiB,OAAO,aAAuD;CAC3F,IAAI,QAAQ,IAAI,MAAM,CAAC,QAAQ,OAAO,SAAS,CAAC,cAAc;CAE9D,MAAM,sBAAsB,SAAS,QAAQ,QAAQ,OAAO,CAAC,iBAAiB,GAAG,CAAC;CAElF,IAAI,oBAAoB,WAAW,GAAG;CAQtC,IAAI,CAAC,OAJgB,MAFK,OAAO,mBAEA,QAAQ,EACxC,SAAS,GAAG,oBAAoB,WAAW,IAAI,YAAY,WAAW,6BAA6B,oBAAoB,KAAK,IAAI,EAAE,2BAA2B,oBAAoB,WAAW,IAAI,OAAO,OAAO,GAC/M,CAAC,GAEY;CAIb,OAAM,MAFiB,OAAO,uBAEf,eAAe,qBAAiC,EAAE,KAAK,KAAK,CAAC;AAC7E;AAEA,MAAa,kBAA2B,WAA0C;CACjF,OAAO,SAAS,MAAM,IAAI,SAAU,CAAC;AACtC;AAEA,MAAa,cAAc;CAC1B,MAAM,EACL,MAAM,eACP;CACA,iBAAiB,UAAkB;EAClC,KAAK;GACJ,MAAM,CAAC;GACP,UAAU,CAAC;GACX,KAAK;IAAE,KAAK,KAAK;IAAQ,OAAO;GAAE;GAClC,OAAO,CAAC,GAAG,KAAK,MAAM;GACtB,QAAQ,CAAC;GACT,MAAM;EACP;EACA,cAAc;EACd,UAAU,EAAE,SAAS,KAAK;EAC1B,aAAa,EACZ,SAAS,CAAC,EACX;CACD;AACD;AAEA,MAAa,sBAA+B;CAC3C,IAAI,QAAQ,IAAI,IACf,OAAO;CAGR,IAAI,yBAAyB,GAC5B,OAAO;CAGR,OACC,QAAQ,QAAQ,IAAI,UAAU,KAC3B,QAAQ,QAAQ,IAAI,UAAU,KAC9B,QAAQ,QAAQ,IAAI,aAAa,KACjC,QAAQ,QAAQ,IAAI,GAAG,KACvB,QAAQ,QAAQ,IAAI,IAAI,KACvB,QAAQ,QAAQ,IAAI,eAAe,KAAK,CAAC,QAAQ,IAAI;AAE3D;AAEA,MAAa,iCAA0C;CACtD,OACC,QAAQ,QAAQ,IAAI,UAAU,KAC3B,QAAQ,QAAQ,IAAI,kBAAkB,KACtC,QAAQ,QAAQ,IAAI,sBAAsB,WAAW,aAAa,CAAC;AAExE"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { isFunction, isObjectAndNotArray, type Awaitable } from \"@zayne-labs/toolkit-type-helpers\";\nimport type { ESLint } from \"eslint\";\nimport { isPackageExists } from \"local-pkg\";\nimport type { TypedFlatConfigItem } from \"./types\";\n\nexport const isObject = <TObject extends object>(value: unknown): value is TObject => {\n\treturn isObjectAndNotArray(value);\n};\n\n/**\n * @description - Combine array and non-array configs into a single array.\n */\nexport const combine = async (\n\t...configs: Array<Awaitable<TypedFlatConfigItem | TypedFlatConfigItem[]>>\n): Promise<TypedFlatConfigItem[]> => {\n\t// eslint-disable-next-line ts-eslint/await-thenable -- False positive\n\tconst resolved = await Promise.all(configs);\n\n\treturn resolved.flat();\n};\n\nexport const interopDefault = async <TModule>(\n\tmodule: Awaitable<TModule>\n): Promise<TModule extends { default: infer TDefaultExport } ? TDefaultExport : TModule> => {\n\tconst resolved = await module;\n\n\t// eslint-disable-next-line ts-eslint/no-unnecessary-condition -- casting is necessary to prevent assignability ts issues at call-site\n\treturn (resolved as { default: never }).default ?? resolved;\n};\n\n/**\n * @description - Rename plugin prefixes in a rule object.\n * Accepts a map of prefixes to rename.\n *\n * @example\n * ```ts\n * import { renameRules } from '@zayne-labs/eslint-config'\n *\n * export default [{\n * rules: renameRules(\n * {\n * '@typescript-eslint/indent': 'error'\n * },\n * { '@typescript-eslint': 'ts-eslint' }\n * )\n * }]\n * ```\n */\nexport const renameRules = (\n\trules: Record<string, unknown> | undefined,\n\trenameMap: Record<string, string>,\n\tseparator = \"/\"\n): TypedFlatConfigItem[\"rules\"] | undefined => {\n\tif (!rules) return;\n\n\tconst renamedRulesEntries = Object.entries(rules).map(([ruleName, ruleValue]) => {\n\t\tfor (const [oldRulePrefix, newRulePrefix] of Object.entries(renameMap)) {\n\t\t\tconst oldRulePrefixWithSeparator = `${oldRulePrefix}${separator}`;\n\n\t\t\tif (!ruleName.startsWith(oldRulePrefixWithSeparator)) continue;\n\n\t\t\tconst restOfRuleNameWithoutSeparator = ruleName.slice(oldRulePrefixWithSeparator.length);\n\n\t\t\t// == Skip if rule name still contains separator, which signifies a nested rule prefix that we don't want to rename\n\t\t\tif (restOfRuleNameWithoutSeparator.includes(separator)) continue;\n\n\t\t\tconst newRuleName = `${newRulePrefix}${separator}${restOfRuleNameWithoutSeparator}`;\n\n\t\t\treturn [newRuleName, ruleValue];\n\t\t}\n\n\t\treturn [ruleName, ruleValue];\n\t});\n\n\treturn Object.fromEntries(renamedRulesEntries) as TypedFlatConfigItem[\"rules\"];\n};\n\nexport const renamePlugins = (\n\tplugins: Record<string, unknown> | undefined,\n\trenameMap: Record<string, string>\n): Record<string, ESLint.Plugin> | undefined => {\n\tif (!plugins) return;\n\n\tconst renamedPluginEntries = Object.entries(plugins).map(([pluginName, pluginValue]) => {\n\t\tif (Object.hasOwn(renameMap, pluginName)) {\n\t\t\tconst newPluginName = renameMap[pluginName];\n\n\t\t\treturn [newPluginName, pluginValue];\n\t\t}\n\n\t\treturn [pluginName, pluginValue];\n\t});\n\n\treturn Object.fromEntries(renamedPluginEntries) as Record<string, ESLint.Plugin>;\n};\n\ntype OverrideConfigsOptions = {\n\tconfigArray: TypedFlatConfigItem[];\n\toverrides: TypedFlatConfigItem | ((config: TypedFlatConfigItem) => TypedFlatConfigItem);\n};\n\nconst getResolvedOverrides = (options: {\n\tconfigItem: TypedFlatConfigItem;\n\toverrides: OverrideConfigsOptions[\"overrides\"] | undefined;\n}) => {\n\tconst { configItem, overrides } = options;\n\n\treturn isFunction(overrides) ? overrides(configItem) : overrides;\n};\n\n/**\n * @description - Override configurations in a flat configs array with either a static config object or a function that returns a config object\n * @param options - Configuration options\n * @param options.configs - Array of flat config items to override\n * @param options.overrides - Either a config object to merge or a function that takes a config and returns overrides\n * @returns Array of merged config items with overrides applied\n *\n * @example\n * ```ts\n * import { overrideConfigs } from '@zayne-labs/eslint-config'\n *\n * // Override with static config\n * overrideConfigs({\n * configArray: existingConfigs,\n * overrides: {\n * rules: {\n * 'no-console': 'error'\n * }\n * }\n * })\n *\n * // Override with function\n * overrideConfigs({\n * configArray: existingConfigs,\n * overrides: (config) => ({\n * ...config,\n * rules: {\n * ...config.rules,\n * 'no-console': 'error'\n * }\n * })\n * })\n * ```\n */\nexport const overrideConfigs = (options: OverrideConfigsOptions): TypedFlatConfigItem[] => {\n\tconst { configArray, overrides } = options;\n\n\treturn configArray.map((configItem) => ({\n\t\t...configItem,\n\t\t...getResolvedOverrides({ configItem, overrides }),\n\t}));\n};\n\ntype RenamePluginInConfigsOptions = {\n\tconfigArray: OverrideConfigsOptions[\"configArray\"];\n\toverrides?: OverrideConfigsOptions[\"overrides\"];\n\trenameMap: Record<string, string>;\n};\n\n/**\n * @description - Rename plugin names and rules in a flat configs array\n *\n * @param options - Configuration options\n * @param options.configArray - Array of flat config items to process\n * @param options.overrides - Optional config overrides to apply\n * @param options.renameMap - Map of old plugin names to new names\n *\n * @example\n * ```ts\n * import { renamePluginInConfigs } from '@zayne-labs/eslint-config'\n * import someConfigs from './some-configs'\n *\n * renamePluginInConfigs({\n * configArray: someConfigs,\n * renameMap: {\n * '@typescript-eslint': 'ts-eslint',\n * 'import-x': 'import',\n * }\n * })\n * ```\n */\n\nexport const renamePluginInConfigs = (options: RenamePluginInConfigsOptions): TypedFlatConfigItem[] => {\n\tconst { configArray, overrides, renameMap } = options;\n\n\tconst renamedConfigs = overrideConfigs({\n\t\tconfigArray,\n\t\toverrides: (configItem) => ({\n\t\t\t...getResolvedOverrides({ configItem, overrides }),\n\n\t\t\t...(isObject(configItem.plugins) && {\n\t\t\t\tplugins: renamePlugins(configItem.plugins, renameMap),\n\t\t\t}),\n\t\t\t...(isObject(configItem.rules) && {\n\t\t\t\trules: renameRules(configItem.rules, renameMap),\n\t\t\t}),\n\t\t}),\n\t});\n\n\treturn renamedConfigs;\n};\n\nconst scopeUrl = fileURLToPath(new URL(\".\", import.meta.url));\nconst isCwdInScope = isPackageExists(\"@zayne-labs/eslint-config\");\n\nexport const isPackageInScope = (name: string): boolean => isPackageExists(name, { paths: [scopeUrl] });\n\n/**\n * @description\n * - Ensures that packages are installed in the current scope.\n * - If they are not installed, and the user is in a TTY, and the user is not in a CI environment,\n * and the user is in the same scope as this package, then prompt the user to\n * install the packages.\n *\n * @param packages - The packages to ensure are installed.\n */\nexport const ensurePackages = async (packages: Array<string | undefined>): Promise<void> => {\n\tif (!isCwdInScope || process.env.CI || !process.stdout.isTTY) return;\n\n\tconst nonExistingPackages = packages.filter((pkg) => pkg && !isPackageInScope(pkg));\n\n\tif (nonExistingPackages.length === 0) return;\n\n\tconst clackPrompt = await import(\"@clack/prompts\");\n\n\tconst result = await clackPrompt.confirm({\n\t\tmessage: `${nonExistingPackages.length === 1 ? \"Package\" : \"Packages\"} required for this config: ${nonExistingPackages.join(\", \")}. Do you want to install ${nonExistingPackages.length === 1 ? \"it\" : \"them\"}?`,\n\t});\n\n\tif (!result) return;\n\n\tconst antfuPkg = await import(\"@antfu/install-pkg\");\n\n\tawait antfuPkg.installPackage(nonExistingPackages as string[], { dev: true });\n};\n\nexport const resolveOptions = <TObject>(option: boolean | TObject | undefined) => {\n\treturn isObject(option) ? option : ({} as TObject);\n};\n\nexport const parserPlain = {\n\tmeta: {\n\t\tname: \"parser-plain\",\n\t},\n\tparseForESLint: (code: string) => ({\n\t\tast: {\n\t\t\tbody: [],\n\t\t\tcomments: [],\n\t\t\tloc: { end: code.length, start: 0 },\n\t\t\trange: [0, code.length],\n\t\t\ttokens: [],\n\t\t\ttype: \"Program\",\n\t\t},\n\t\tscopeManager: null,\n\t\tservices: { isPlain: true },\n\t\tvisitorKeys: {\n\t\t\tProgram: [],\n\t\t},\n\t}),\n};\n\nexport const isInEditorEnv = (): boolean => {\n\tif (process.env.CI) {\n\t\treturn false;\n\t}\n\n\tif (isInGitHooksOrLintStaged()) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tBoolean(process.env.VSCODE_PID)\n\t\t|| Boolean(process.env.VSCODE_CWD)\n\t\t|| Boolean(process.env.JETBRAINS_IDE)\n\t\t|| Boolean(process.env.VIM)\n\t\t|| Boolean(process.env.NVIM)\n\t\t|| (Boolean(process.env.ZED_ENVIRONMENT) && !process.env.ZED_TERM)\n\t);\n};\n\nexport const isInGitHooksOrLintStaged = (): boolean => {\n\treturn (\n\t\tBoolean(process.env.GIT_PARAMS)\n\t\t|| Boolean(process.env.VSCODE_GIT_COMMAND)\n\t\t|| Boolean(process.env.npm_lifecycle_script?.startsWith(\"lint-staged\"))\n\t);\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@zayne-labs/eslint-config",
3
3
  "type": "module",
4
- "version": "0.13.13",
4
+ "version": "0.13.15",
5
5
  "description": "Zayne Labs' ESLint config preset",
6
6
  "author": "Ryan Zayne",
7
7
  "license": "MIT",
@@ -20,7 +20,9 @@
20
20
  "./constants/*": "./dist/constants/*.js",
21
21
  "./utils": "./dist/utils.js"
22
22
  },
23
- "bin": "./bin/index.js",
23
+ "bin": {
24
+ "eslint-config": "./bin/index.js"
25
+ },
24
26
  "files": [
25
27
  "bin",
26
28
  "dist"
@@ -29,28 +31,28 @@
29
31
  "node": ">=20.x"
30
32
  },
31
33
  "peerDependencies": {
32
- "@eslint-react/eslint-plugin": "^5.8.1",
33
- "@next/eslint-plugin-next": "^16.2.6",
34
- "@tanstack/eslint-plugin-query": "^5.100.11",
34
+ "@eslint-react/eslint-plugin": "^5.19.0",
35
+ "@next/eslint-plugin-next": "^16.3.4",
36
+ "@tanstack/eslint-plugin-query": "^5.102.8",
35
37
  "@tanstack/eslint-plugin-router": "^1.162.0",
36
- "astro-eslint-parser": "^1.4.0",
37
- "eslint": "^10.4.0",
38
- "eslint-config-expo": "^55.0.1",
39
- "eslint-plugin-astro": "^1.7.0",
40
- "eslint-plugin-better-tailwindcss": "^4.5.0",
38
+ "astro-eslint-parser": "^3.1.0",
39
+ "eslint": "^10.10.0",
40
+ "eslint-config-expo": "^57.0.2",
41
+ "eslint-plugin-astro": "^3.1.0",
42
+ "eslint-plugin-better-tailwindcss": "^4.7.0",
41
43
  "eslint-plugin-depend": "^1.5.0",
42
- "eslint-plugin-erasable-syntax-only": "^0.4.1",
44
+ "eslint-plugin-erasable-syntax-only": "^0.7.1",
43
45
  "eslint-plugin-jsx-a11y": "^6.10.2",
44
46
  "eslint-plugin-react-hooks": "^7.1.1",
45
- "eslint-plugin-react-refresh": "^0.5.2",
46
- "eslint-plugin-react-you-might-not-need-an-effect": "^0.10.1",
47
- "eslint-plugin-solid": "^0.14.5",
48
- "eslint-plugin-svelte": "^3.17.1",
49
- "eslint-plugin-vue": "^10.9.1",
50
- "eslint-plugin-vuejs-accessibility": "^2.5.0",
47
+ "eslint-plugin-react-refresh": "^0.5.6",
48
+ "eslint-plugin-react-you-might-not-need-an-effect": "^1.0.2",
49
+ "eslint-plugin-solid": "^0.17.0",
50
+ "eslint-plugin-svelte": "^3.23.0",
51
+ "eslint-plugin-vue": "^10.11.0",
52
+ "eslint-plugin-vuejs-accessibility": "^2.6.0",
51
53
  "eslint-processor-vue-blocks": "^2.0.0",
52
- "svelte-eslint-parser": "^1.6.1",
53
- "vue-eslint-parser": "^10.4.0"
54
+ "svelte-eslint-parser": "^1.8.1",
55
+ "vue-eslint-parser": "^10.4.1"
54
56
  },
55
57
  "peerDependenciesMeta": {
56
58
  "@eslint-react/eslint-plugin": {
@@ -118,86 +120,88 @@
118
120
  }
119
121
  },
120
122
  "dependencies": {
121
- "@antfu/install-pkg": "1.1.0",
122
- "@clack/prompts": "1.4.0",
123
- "@eslint-community/eslint-plugin-eslint-comments": "4.7.1",
124
- "@eslint-react/kit": "5.8.1",
125
- "@eslint/compat": "2.1.0",
123
+ "@antfu/install-pkg": "2.0.1",
124
+ "@clack/prompts": "1.8.0",
125
+ "@eslint-community/eslint-plugin-eslint-comments": "4.8.0",
126
+ "@eslint-react/kit": "5.19.0",
126
127
  "@eslint/js": "10.0.1",
127
- "@eslint/markdown": "8.0.1",
128
+ "@eslint/markdown": "8.0.3",
128
129
  "@stylistic/eslint-plugin": "5.10.0",
129
- "@zayne-labs/toolkit-core": "0.12.54",
130
- "@zayne-labs/toolkit-type-helpers": "0.12.54",
131
- "ansis": "4.3.0",
130
+ "@zayne-labs/toolkit-core": "0.12.59",
131
+ "@zayne-labs/toolkit-type-helpers": "0.12.59",
132
+ "ansis": "4.3.1",
132
133
  "cac": "7.0.0",
133
- "eslint-config-flat-gitignore": "2.3.0",
134
+ "eslint-config-flat-gitignore": "2.4.0",
134
135
  "eslint-flat-config-utils": "3.2.0",
135
- "eslint-import-resolver-typescript": "4.4.4",
136
+ "eslint-import-resolver-typescript": "4.4.5",
136
137
  "eslint-merge-processors": "2.0.0",
137
- "eslint-plugin-command": "^3.5.2",
138
- "eslint-plugin-import-x": "4.16.2",
139
- "eslint-plugin-jsdoc": "62.9.0",
140
- "eslint-plugin-jsonc": "3.1.2",
141
- "eslint-plugin-n": "18.0.1",
142
- "eslint-plugin-perfectionist": "5.9.0",
143
- "eslint-plugin-pnpm": "1.6.0",
144
- "eslint-plugin-security": "4.0.0",
145
- "eslint-plugin-toml": "1.3.1",
146
- "eslint-plugin-unicorn": "64.0.0",
147
- "eslint-plugin-yml": "3.3.2",
148
- "globals": "17.6.0",
149
- "jsonc-eslint-parser": "3.1.0",
150
- "local-pkg": "1.1.2",
138
+ "eslint-plugin-baseline-js": "^0.7.1",
139
+ "eslint-plugin-command": "^4.0.0",
140
+ "eslint-plugin-import-x": "4.17.1",
141
+ "eslint-plugin-jsdoc": "64.3.6",
142
+ "eslint-plugin-jsonc": "3.4.2",
143
+ "eslint-plugin-n": "18.3.0",
144
+ "eslint-plugin-perfectionist": "5.11.0",
145
+ "eslint-plugin-pnpm": "1.9.1",
146
+ "eslint-plugin-regexp": "^3.3.0",
147
+ "eslint-plugin-security": "4.0.1",
148
+ "eslint-plugin-toml": "1.5.0",
149
+ "eslint-plugin-unicorn": "74.0.0",
150
+ "eslint-plugin-yml": "3.8.1",
151
+ "globals": "17.12.0",
152
+ "jsonc-eslint-parser": "3.3.0",
153
+ "local-pkg": "1.2.1",
151
154
  "parse-gitignore": "2.0.0",
152
- "pnpm-workspace-yaml": "^1.6.0",
155
+ "pnpm-workspace-yaml": "^1.9.1",
153
156
  "toml-eslint-parser": "1.0.3",
154
- "typescript-eslint": "8.59.4",
155
- "yaml-eslint-parser": "2.0.0"
157
+ "typescript-eslint": "8.70.0",
158
+ "yaml-eslint-parser": "2.1.0"
156
159
  },
157
160
  "devDependencies": {
158
- "@arethetypeswrong/cli": "0.18.2",
159
- "@changesets/cli": "2.31.0",
160
- "@eslint-react/eslint-plugin": "^5.8.1",
161
- "@next/eslint-plugin-next": "^16.2.6",
162
- "@tanstack/eslint-plugin-query": "^5.100.11",
161
+ "@arethetypeswrong/cli": "0.18.5",
162
+ "@changesets/cli": "3.0.2",
163
+ "@eslint-react/eslint-plugin": "^5.19.0",
164
+ "@next/eslint-plugin-next": "^16.3.4",
165
+ "@tanstack/eslint-plugin-query": "^5.102.8",
163
166
  "@tanstack/eslint-plugin-router": "^1.162.0",
164
167
  "@total-typescript/ts-reset": "0.6.1",
165
168
  "@types/eslint-plugin-jsx-a11y": "6.10.1",
166
- "@types/node": "25.9.0",
167
- "@typescript-eslint/parser": "8.59.4",
168
- "@typescript-eslint/types": "8.59.4",
169
- "@typescript-eslint/utils": "8.59.4",
170
- "astro-eslint-parser": "^1.4.0",
171
- "concurrently": "9.2.1",
169
+ "@types/node": "26.5.0",
170
+ "@typescript-eslint/parser": "8.70.0",
171
+ "@typescript-eslint/types": "8.70.0",
172
+ "@typescript-eslint/utils": "8.70.0",
173
+ "@zayne-labs/tsconfig": "0.13.15",
174
+ "astro-eslint-parser": "^3.1.0",
175
+ "concurrently": "10.0.5",
172
176
  "cross-env": "10.1.0",
173
- "eslint": "^10.4.0",
174
- "eslint-config-expo": "^55.0.1",
175
- "eslint-plugin-astro": "^1.7.0",
176
- "eslint-plugin-better-tailwindcss": "^4.5.0",
177
+ "eslint": "^10.10.0",
178
+ "eslint-config-expo": "^57.0.2",
179
+ "eslint-plugin-astro": "^3.1.0",
180
+ "eslint-plugin-better-tailwindcss": "^4.7.0",
177
181
  "eslint-plugin-depend": "^1.5.0",
178
- "eslint-plugin-erasable-syntax-only": "^0.4.1",
182
+ "eslint-plugin-erasable-syntax-only": "^0.7.1",
179
183
  "eslint-plugin-jsx-a11y": "^6.10.2",
180
184
  "eslint-plugin-react-hooks": "^7.1.1",
181
- "eslint-plugin-react-refresh": "^0.5.2",
182
- "eslint-plugin-react-you-might-not-need-an-effect": "^0.10.1",
183
- "eslint-plugin-solid": "^0.14.5",
184
- "eslint-plugin-svelte": "^3.17.1",
185
- "eslint-plugin-vue": "^10.9.1",
186
- "eslint-plugin-vuejs-accessibility": "^2.5.0",
185
+ "eslint-plugin-react-refresh": "^0.5.6",
186
+ "eslint-plugin-react-you-might-not-need-an-effect": "^1.0.2",
187
+ "eslint-plugin-solid": "^0.17.0",
188
+ "eslint-plugin-svelte": "^3.23.0",
189
+ "eslint-plugin-vue": "^10.11.0",
190
+ "eslint-plugin-vuejs-accessibility": "^2.6.0",
187
191
  "eslint-processor-vue-blocks": "^2.0.0",
188
192
  "eslint-typegen": "2.3.1",
189
193
  "find-up-simple": "1.0.1",
190
194
  "husky": "9.1.7",
191
- "pkg-pr-new": "0.0.74",
192
- "prettier": "^3.8.3",
193
- "publint": "0.3.21",
194
- "svelte-eslint-parser": "^1.6.1",
195
- "tailwindcss": "4.3.0",
196
- "tsdown": "0.22.0",
197
- "tsx": "4.22.2",
195
+ "pkg-pr-new": "0.0.88",
196
+ "prettier": "^3.9.6",
197
+ "publint": "0.3.24",
198
+ "svelte-eslint-parser": "^1.8.1",
199
+ "tailwindcss": "4.3.3",
200
+ "tsdown": "0.23.0",
201
+ "tsx": "4.23.13",
198
202
  "typescript": "6.0.3",
199
- "vue-eslint-parser": "^10.4.0",
200
- "@zayne-labs/tsconfig": "0.13.13"
203
+ "vitest": "^5.0.0",
204
+ "vue-eslint-parser": "^10.4.1"
201
205
  },
202
206
  "publishConfig": {
203
207
  "access": "public",
@@ -216,6 +220,7 @@
216
220
  "lint:type-check": "pnpm typegen && tsc --pretty -p tsconfig.json",
217
221
  "release": "pnpm publish --no-git-checks",
218
222
  "release:test": "pnpx pkg-pr-new publish",
223
+ "test": "pnpm build && vitest run",
219
224
  "typegen": "tsx scripts/typegen.ts && tsx scripts/versiongen.ts",
220
225
  "version-package": "changeset version"
221
226
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsxRules-BAjKnxGs.js","names":[],"sources":["../src/rules/react/utils.ts","../src/rules/react/jsxRules.ts"],"sourcesContent":["/* eslint-disable ts-eslint/no-unsafe-enum-comparison -- Ignore, I don't want the enum to be bundled */\nimport type { TSESTree } from \"@typescript-eslint/types\";\n\nexport const stringifyJsx = (\n\tnode:\n\t\t| TSESTree.JSXClosingElement\n\t\t| TSESTree.JSXClosingFragment\n\t\t| TSESTree.JSXIdentifier\n\t\t| TSESTree.JSXMemberExpression\n\t\t| TSESTree.JSXNamespacedName\n\t\t| TSESTree.JSXOpeningElement\n\t\t| TSESTree.JSXOpeningFragment\n\t\t| TSESTree.JSXText\n): string => {\n\tswitch (node.type) {\n\t\tcase \"JSXClosingElement\": {\n\t\t\t// Closing tags like \"</div>\"\n\t\t\treturn `</${stringifyJsx(node.name)}>`;\n\t\t}\n\t\tcase \"JSXClosingFragment\": {\n\t\t\t// Fragment closing syntax \"</>\"\n\t\t\treturn \"</>\";\n\t\t}\n\t\tcase \"JSXIdentifier\": {\n\t\t\t// Simple element names like \"div\" or component names like \"Button\"\n\t\t\treturn node.name;\n\t\t}\n\t\tcase \"JSXMemberExpression\": {\n\t\t\t// Dot-notation components like \"React.Fragment\" or \"Namespace.Component\"\n\t\t\treturn `${stringifyJsx(node.object)}.${stringifyJsx(node.property)}`;\n\t\t}\n\t\tcase \"JSXNamespacedName\": {\n\t\t\t// XML-style namespaced elements like \"svg:path\"\n\t\t\treturn `${node.namespace.name}:${node.name.name}`;\n\t\t}\n\t\tcase \"JSXOpeningElement\": {\n\t\t\t// Opening tags like \"<div>\"\n\t\t\treturn `<${stringifyJsx(node.name)}>`;\n\t\t}\n\t\tcase \"JSXOpeningFragment\": {\n\t\t\t// Fragment opening syntax \"<>\"\n\t\t\treturn \"<>\";\n\t\t}\n\t\tcase \"JSXText\": {\n\t\t\t// Text content inside JSX\n\t\t\treturn node.value;\n\t\t}\n\t\tdefault: {\n\t\t\treturn \"\";\n\t\t}\n\t}\n};\n","/* eslint-disable ts-eslint/no-unsafe-enum-comparison -- Ignore, I don't want the enum to be bundled */\n/* eslint-disable unicorn/consistent-function-scoping -- Ignore */\nimport eslintReactKit, { type RuleFunction } from \"@eslint-react/kit\";\nimport type { ESLintUtils } from \"@typescript-eslint/utils\";\nimport type { RuleContext } from \"@typescript-eslint/utils/ts-eslint\";\nimport { stringifyJsx } from \"./utils\";\n\ntype OptionsShortHand = readonly [\"always\" | \"never\" | null];\n\ntype MessageID = \"default\";\n\ntype RuleDefinition<TRuleContext = RuleContext<MessageID, OptionsShortHand>> = (\n\tcontext: TRuleContext,\n\ttoolkit: Parameters<RuleFunction>[1]\n) => ESLintUtils.RuleListener;\n\ntype RuleWithMetaAndName = Omit<ESLintUtils.RuleWithMetaAndName<OptionsShortHand, MessageID>, \"create\">;\n\nconst jsxShorthandBoolean = (): RuleDefinition => (context) => {\n\tconst policy = (context.options[0] ?? \"never\") satisfies OptionsShortHand[0];\n\n\treturn {\n\t\tJSXAttribute: (node) => {\n\t\t\tconst { value } = node;\n\t\t\tconst propName = stringifyJsx(node.name);\n\n\t\t\tswitch (true) {\n\t\t\t\tcase policy === \"always\"\n\t\t\t\t\t&& value?.type === \"JSXExpressionContainer\"\n\t\t\t\t\t&& value.expression.type === \"Literal\"\n\t\t\t\t\t&& value.expression.value === true: {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: `Omit attribute value for '${propName}'.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => fixer.removeRange([node.name.range[1], value.range[1]]),\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t});\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase policy === \"never\" && value == null: {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: `Set attribute value for '${propName}'.`,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => fixer.insertTextAfter(node.name, `={true}`),\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode: node.value ?? node,\n\t\t\t\t\t});\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tdefault: {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n};\n\nconst jsxShorthandBooleanMeta = {\n\tmeta: {\n\t\tdefaultOptions: [\"never\"],\n\t\tdocs: {\n\t\t\tdescription:\n\t\t\t\t\"Enforces whether to use shorthand syntax for boolean attributes (e.g., 'disabled') or not\",\n\t\t},\n\t\tfixable: \"code\",\n\t\thasSuggestions: true,\n\t\tmessages: {\n\t\t\tdefault: \"{{message}}\",\n\t\t},\n\t\tschema: [\n\t\t\t{\n\t\t\t\tenum: [\"always\", \"never\"],\n\t\t\t\ttype: \"string\",\n\t\t\t},\n\t\t],\n\t\ttype: \"suggestion\",\n\t},\n\tname: \"jsx-shorthand-boolean\",\n} as const satisfies RuleWithMetaAndName;\n\nconst jsxShorthandFragment = (): RuleDefinition => (context, toolkit) => {\n\tconst policy = (context.options[0] ?? \"always\") satisfies OptionsShortHand[0];\n\n\tswitch (policy) {\n\t\tcase \"always\": {\n\t\t\treturn {\n\t\t\t\tJSXElement: (node) => {\n\t\t\t\t\tif (node.openingElement.attributes.length > 0) return;\n\n\t\t\t\t\tconst name = stringifyJsx(node.openingElement.name);\n\n\t\t\t\t\tconst isFragmentNode = name === \"Fragment\" || name === \"React.Fragment\";\n\n\t\t\t\t\tconst variableToCheck = name.split(\".\")[0] ?? name;\n\n\t\t\t\t\tconst isFragment =\n\t\t\t\t\t\tisFragmentNode\n\t\t\t\t\t\t&& toolkit.is.APIFromReact(\n\t\t\t\t\t\t\tvariableToCheck,\n\t\t\t\t\t\t\tcontext.sourceCode.getScope(node.openingElement)\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif (!isFragment) return;\n\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: \"Use fragment shorthand syntax instead of 'Fragment' component.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => {\n\t\t\t\t\t\t\tif (node.closingElement == null) {\n\t\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.openingElement.range[0], node.openingElement.range[1]],\n\t\t\t\t\t\t\t\t\t\"<\"\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.closingElement.range[0], node.closingElement.range[1]],\n\t\t\t\t\t\t\t\t\t\"</>\"\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tcase \"never\": {\n\t\t\treturn {\n\t\t\t\tJSXFragment: (node) => {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tmessage: \"Use 'Fragment' component instead of fragment shorthand syntax.\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfix: (fixer) => {\n\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.openingFragment.range[0], node.openingFragment.range[1]],\n\t\t\t\t\t\t\t\t\t`<Fragment>`\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tfixer.replaceTextRange(\n\t\t\t\t\t\t\t\t\t[node.closingFragment.range[0], node.closingFragment.range[1]],\n\t\t\t\t\t\t\t\t\t`</Fragment>`\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t];\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmessageId: \"default\",\n\t\t\t\t\t\tnode,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tdefault: {\n\t\t\treturn {};\n\t\t}\n\t}\n};\n\nconst jsxShorthandFragmentMeta = {\n\tmeta: {\n\t\t...jsxShorthandBooleanMeta.meta,\n\t\tdefaultOptions: [\"always\"],\n\t\tdocs: {\n\t\t\tdescription: \"Enforces whether to use fragment shorthand syntax (<>...</>) or not\",\n\t\t},\n\t},\n\tname: \"jsx-shorthand-fragment\",\n} as const satisfies RuleWithMetaAndName;\n\nconst RuleMetaArray = [jsxShorthandBooleanMeta, jsxShorthandFragmentMeta];\n\nexport const getCustomJsxPlugin = () => {\n\tconst plugin = eslintReactKit()\n\t\t.use(jsxShorthandBoolean as () => RuleDefinition<RuleContext<\"default\", readonly unknown[]>>)\n\t\t.use(jsxShorthandFragment as () => RuleDefinition<RuleContext<\"default\", readonly unknown[]>>)\n\t\t.getPlugin();\n\n\tfor (const ruleMeta of RuleMetaArray) {\n\t\tconst rule = plugin.rules?.[ruleMeta.name];\n\n\t\trule?.meta && Object.assign(rule.meta, ruleMeta.meta);\n\t}\n\n\treturn plugin;\n};\n"],"mappings":"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"}