@lincy/eslint-config 7.1.2 → 8.0.0

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/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { FlatConfigComposer } from "eslint-flat-config-utils";
2
2
  import process from "node:process";
3
- import fs from "node:fs/promises";
3
+ import fsPromises from "node:fs/promises";
4
4
  import { fileURLToPath } from "node:url";
5
- import fs$1 from "node:fs";
5
+ import fs from "node:fs";
6
6
  import path from "node:path";
7
7
  import { getPackageInfoSync, isPackageExists } from "local-pkg";
8
8
  import pluginE18e from "@e18e/eslint-plugin";
@@ -26,7 +26,7 @@ async function findUp(name, { cwd = process.cwd(), type = "file", stopAt } = {})
26
26
  while (directory) {
27
27
  const filePath = isAbsoluteName ? name : path.join(directory, name);
28
28
  try {
29
- const stats = await fs.stat(filePath);
29
+ const stats = await fsPromises.stat(filePath);
30
30
  if (type === "file" && stats.isFile() || type === "directory" && stats.isDirectory()) return filePath;
31
31
  } catch {}
32
32
  if (directory === stopAt || directory === root) break;
@@ -41,7 +41,7 @@ function findUpSync(name, { cwd = process.cwd(), type = "file", stopAt } = {}) {
41
41
  while (directory) {
42
42
  const filePath = isAbsoluteName ? name : path.join(directory, name);
43
43
  try {
44
- const stats = fs$1.statSync(filePath, { throwIfNoEntry: false });
44
+ const stats = fs.statSync(filePath, { throwIfNoEntry: false });
45
45
  if (type === "file" && stats?.isFile() || type === "directory" && stats?.isDirectory()) return filePath;
46
46
  } catch {}
47
47
  if (directory === stopAt || directory === root) break;
@@ -49,22 +49,6 @@ function findUpSync(name, { cwd = process.cwd(), type = "file", stopAt } = {}) {
49
49
  }
50
50
  }
51
51
  //#endregion
52
- //#region src/configs/comments.ts
53
- async function comments(options = {}) {
54
- const { overrides = {} } = options;
55
- return [{
56
- name: "eslint/comments/rules",
57
- plugins: { "eslint-comments": pluginComments },
58
- rules: {
59
- "eslint-comments/no-aggregating-enable": "error",
60
- "eslint-comments/no-duplicate-disable": "error",
61
- "eslint-comments/no-unlimited-disable": "error",
62
- "eslint-comments/no-unused-enable": "error",
63
- ...overrides
64
- }
65
- }];
66
- }
67
- //#endregion
68
52
  //#region src/globs.ts
69
53
  const GLOB_SRC_EXT = "?([cm])[jt]s?(x)";
70
54
  const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
@@ -145,6 +129,163 @@ const GLOB_EXCLUDE = [
145
129
  "**/.*/skills"
146
130
  ];
147
131
  //#endregion
132
+ //#region src/utils.ts
133
+ const scopeUrl = fileURLToPath(new URL(".", import.meta.url));
134
+ const isCwdInScope = isPackageExists("@antfu/eslint-config");
135
+ const parserPlain = {
136
+ meta: { name: "parser-plain" },
137
+ parseForESLint: (code) => ({
138
+ ast: {
139
+ body: [],
140
+ comments: [],
141
+ loc: {
142
+ end: code.length,
143
+ start: 0
144
+ },
145
+ range: [0, code.length],
146
+ tokens: [],
147
+ type: "Program"
148
+ },
149
+ scopeManager: null,
150
+ services: { isPlain: true },
151
+ visitorKeys: { Program: [] }
152
+ })
153
+ };
154
+ /**
155
+ * Combine array and non-array configs into a single array.
156
+ */
157
+ async function combine(...configs) {
158
+ return (await Promise.all(configs)).flat();
159
+ }
160
+ function renameRules(rules, map) {
161
+ return Object.fromEntries(Object.entries(rules).map(([key, value]) => {
162
+ for (const [from, to] of Object.entries(map)) if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];
163
+ return [key, value];
164
+ }));
165
+ }
166
+ function renamePluginInConfigs(configs, map) {
167
+ return configs.map((i) => {
168
+ const clone = { ...i };
169
+ if (clone.rules) clone.rules = renameRules(clone.rules, map);
170
+ if (clone.plugins) clone.plugins = Object.fromEntries(Object.entries(clone.plugins).map(([key, value]) => {
171
+ if (key in map) return [map[key], value];
172
+ return [key, value];
173
+ }));
174
+ return clone;
175
+ });
176
+ }
177
+ function toArray(value) {
178
+ return Array.isArray(value) ? value : [value];
179
+ }
180
+ async function interopDefault(m) {
181
+ const resolved = await m;
182
+ return resolved.default || resolved;
183
+ }
184
+ function isPackageInScope(name) {
185
+ return isPackageExists(name, { paths: [scopeUrl] });
186
+ }
187
+ async function ensurePackages(packages) {
188
+ if (process.env.CI || process.stdout.isTTY === false || isCwdInScope === false) return;
189
+ const nonExistingPackages = packages.filter((i) => i && !isPackageInScope(i));
190
+ if (nonExistingPackages.length === 0) return;
191
+ if (await (await import("@clack/prompts")).confirm({
192
+ /** message: `${nonExistingPackages.length === 1 ? 'Package is' : 'Packages are'} required for this config: ${nonExistingPackages.join(', ')}. Do you want to install them?`, */
193
+ message: `此配置需要软件包: ${nonExistingPackages.join(", ")}. 你想安装它们吗?` })) await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
194
+ }
195
+ function isInEditorEnv() {
196
+ if (process.env.CI) return false;
197
+ if (isInGitHooksOrLintStaged()) return false;
198
+ return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM);
199
+ }
200
+ function isInGitHooksOrLintStaged() {
201
+ return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged"));
202
+ }
203
+ //#endregion
204
+ //#region src/configs/antislop.ts
205
+ async function antislop(options = {}) {
206
+ const { cognitiveComplexity = 15, overrides = {}, slop = true, sonarjs = true } = options;
207
+ await ensurePackages([...slop ? ["eslint-plugin-slop"] : [], ...sonarjs ? ["eslint-plugin-sonarjs"] : []]);
208
+ const [pluginSlop, pluginSonarjs] = await Promise.all([slop ? interopDefault(import("eslint-plugin-slop")) : void 0, sonarjs ? interopDefault(import("eslint-plugin-sonarjs")) : void 0]);
209
+ return [
210
+ {
211
+ name: "eslint/antislop/setup",
212
+ plugins: {
213
+ ...slop ? { slop: pluginSlop } : {},
214
+ ...sonarjs ? { sonarjs: pluginSonarjs } : {}
215
+ },
216
+ ...typeof slop === "object" ? { settings: { slop } } : {}
217
+ },
218
+ ...slop ? [{
219
+ files: [
220
+ ...GLOB_ALL_SRC,
221
+ GLOB_JSONC,
222
+ GLOB_TOML,
223
+ GLOB_GRAPHQL
224
+ ],
225
+ /**
226
+ * Markdown code fences are already scanned as part of the raw
227
+ * Markdown text, so exclude the virtual embedded-code files to
228
+ * avoid reporting the same em dash twice
229
+ */
230
+ ignores: [GLOB_MARKDOWN_CODE],
231
+ name: "eslint/antislop/rules/universal",
232
+ rules: { "slop/no-em-dash": "error" }
233
+ }] : [],
234
+ {
235
+ files: [GLOB_SRC],
236
+ name: "eslint/antislop/rules/javascript",
237
+ rules: {
238
+ ...slop ? {
239
+ "slop/max-comment-length": "error",
240
+ "slop/no-chained-type-assertions": "error",
241
+ "slop/no-jargon": "error",
242
+ "slop/no-trivial-functions": "error",
243
+ "slop/no-trivial-type-aliases": "error",
244
+ "slop/prefer-jsdoc": "error"
245
+ } : {},
246
+ ...sonarjs ? {
247
+ ...cognitiveComplexity === false ? {} : { "sonarjs/cognitive-complexity": ["error", cognitiveComplexity] },
248
+ "sonarjs/no-all-duplicated-branches": "error",
249
+ "sonarjs/no-collapsible-if": "error",
250
+ "sonarjs/no-commented-code": "error",
251
+ "sonarjs/no-dead-store": "error",
252
+ "sonarjs/no-duplicated-branches": "error",
253
+ "sonarjs/no-element-overwrite": "error",
254
+ "sonarjs/no-empty-collection": "error",
255
+ "sonarjs/no-gratuitous-expressions": "error",
256
+ "sonarjs/no-identical-conditions": "error",
257
+ "sonarjs/no-identical-expressions": "error",
258
+ "sonarjs/no-identical-functions": "error",
259
+ "sonarjs/no-invariant-returns": "error",
260
+ "sonarjs/no-inverted-boolean-check": "error",
261
+ "sonarjs/no-redundant-boolean": "error",
262
+ "sonarjs/no-redundant-jump": "error",
263
+ "sonarjs/no-unused-collection": "error",
264
+ "sonarjs/no-use-of-empty-return-value": "error",
265
+ "sonarjs/prefer-single-boolean-return": "error"
266
+ } : {},
267
+ ...overrides
268
+ }
269
+ }
270
+ ];
271
+ }
272
+ //#endregion
273
+ //#region src/configs/comments.ts
274
+ async function comments(options = {}) {
275
+ const { overrides = {} } = options;
276
+ return [{
277
+ name: "eslint/comments/rules",
278
+ plugins: { "eslint-comments": pluginComments },
279
+ rules: {
280
+ "eslint-comments/no-aggregating-enable": "error",
281
+ "eslint-comments/no-duplicate-disable": "error",
282
+ "eslint-comments/no-unlimited-disable": "error",
283
+ "eslint-comments/no-unused-enable": "error",
284
+ ...overrides
285
+ }
286
+ }];
287
+ }
288
+ //#endregion
148
289
  //#region src/configs/disables.ts
149
290
  async function disables() {
150
291
  return [
@@ -212,6 +353,7 @@ async function e18e(options = {}) {
212
353
  ...moduleReplacements ? { ...configs.moduleReplacements.rules } : {},
213
354
  ...performanceImprovements ? { ...configs.performanceImprovements.rules } : {},
214
355
  ...type === "lib" ? {} : { "e18e/prefer-static-regex": "off" },
356
+ /** these are a bit opinionated and dangerous (introducing behavioral changes), so we'll disable them by default for now */
215
357
  "e18e/prefer-array-at": "off",
216
358
  "e18e/prefer-array-from-map": "off",
217
359
  "e18e/prefer-array-to-reversed": "off",
@@ -223,78 +365,9 @@ async function e18e(options = {}) {
223
365
  }];
224
366
  }
225
367
  //#endregion
226
- //#region src/utils.ts
227
- const scopeUrl = fileURLToPath(new URL(".", import.meta.url));
228
- const isCwdInScope = isPackageExists("@antfu/eslint-config");
229
- const parserPlain = {
230
- meta: { name: "parser-plain" },
231
- parseForESLint: (code) => ({
232
- ast: {
233
- body: [],
234
- comments: [],
235
- loc: {
236
- end: code.length,
237
- start: 0
238
- },
239
- range: [0, code.length],
240
- tokens: [],
241
- type: "Program"
242
- },
243
- scopeManager: null,
244
- services: { isPlain: true },
245
- visitorKeys: { Program: [] }
246
- })
247
- };
248
- /**
249
- * Combine array and non-array configs into a single array.
250
- */
251
- async function combine(...configs) {
252
- return (await Promise.all(configs)).flat();
253
- }
254
- function renameRules(rules, map) {
255
- return Object.fromEntries(Object.entries(rules).map(([key, value]) => {
256
- for (const [from, to] of Object.entries(map)) if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];
257
- return [key, value];
258
- }));
259
- }
260
- function renamePluginInConfigs(configs, map) {
261
- return configs.map((i) => {
262
- const clone = { ...i };
263
- if (clone.rules) clone.rules = renameRules(clone.rules, map);
264
- if (clone.plugins) clone.plugins = Object.fromEntries(Object.entries(clone.plugins).map(([key, value]) => {
265
- if (key in map) return [map[key], value];
266
- return [key, value];
267
- }));
268
- return clone;
269
- });
270
- }
271
- function toArray(value) {
272
- return Array.isArray(value) ? value : [value];
273
- }
274
- async function interopDefault(m) {
275
- const resolved = await m;
276
- return resolved.default || resolved;
277
- }
278
- function isPackageInScope(name) {
279
- return isPackageExists(name, { paths: [scopeUrl] });
280
- }
281
- async function ensurePackages(packages) {
282
- if (process.env.CI || process.stdout.isTTY === false || isCwdInScope === false) return;
283
- const nonExistingPackages = packages.filter((i) => i && !isPackageInScope(i));
284
- if (nonExistingPackages.length === 0) return;
285
- if (await (await import("@clack/prompts")).confirm({ message: `此配置需要软件包: ${nonExistingPackages.join(", ")}. 你想安装它们吗?` })) await import("@antfu/install-pkg").then((i) => i.installPackage(nonExistingPackages, { dev: true }));
286
- }
287
- function isInEditorEnv() {
288
- if (process.env.CI) return false;
289
- if (isInGitHooksOrLintStaged()) return false;
290
- return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM);
291
- }
292
- function isInGitHooksOrLintStaged() {
293
- return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged"));
294
- }
295
- //#endregion
296
368
  //#region src/configs/stylistic.ts
297
369
  const StylisticConfigDefaults = {
370
+ braceStyle: "stroustrup",
298
371
  indent: 4,
299
372
  jsx: true,
300
373
  lessOpinionated: false,
@@ -304,12 +377,13 @@ const StylisticConfigDefaults = {
304
377
  };
305
378
  async function stylistic(options = {}) {
306
379
  const { overrides = {}, stylistic = StylisticConfigDefaults } = options;
307
- const { indent, jsx, lessOpinionated, quotes, semi } = typeof stylistic === "boolean" ? StylisticConfigDefaults : {
380
+ const { braceStyle, indent, jsx, lessOpinionated, quotes, semi } = typeof stylistic === "boolean" ? StylisticConfigDefaults : {
308
381
  ...StylisticConfigDefaults,
309
382
  ...stylistic
310
383
  };
311
384
  const pluginStylistic = await interopDefault(import("@stylistic/eslint-plugin"));
312
385
  const config = pluginStylistic.configs.customize({
386
+ braceStyle,
313
387
  indent,
314
388
  jsx,
315
389
  pluginName: "style",
@@ -566,6 +640,7 @@ async function javascript(options = {}) {
566
640
  "no-class-assign": "error",
567
641
  "no-compare-neg-zero": "error",
568
642
  "no-cond-assign": ["error", "always"],
643
+ /** 'no-console': ['error', { allow: ['warn', 'error'] }], */
569
644
  "no-console": "off",
570
645
  "no-const-assign": "error",
571
646
  "no-control-regex": "error",
@@ -857,6 +932,11 @@ async function markdown(options = {}) {
857
932
  files,
858
933
  ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
859
934
  name: "eslint/markdown/processor",
935
+ /**
936
+ * `eslint-plugin-markdown` only creates virtual files for code blocks,
937
+ * but not the markdown file itself. We use `eslint-merge-processors` to
938
+ * add a pass-through processor for the markdown file itself.
939
+ */
860
940
  processor: mergeProcessors([markdown.processors.markdown, processorPassThrough])
861
941
  },
862
942
  {
@@ -870,6 +950,7 @@ async function markdown(options = {}) {
870
950
  rules: {
871
951
  ...markdown.configs.recommended.at(0)?.rules,
872
952
  "markdown/fenced-code-language": "off",
953
+ /** https://github.com/eslint/markdown/issues/294 */
873
954
  "markdown/no-missing-label-refs": "off",
874
955
  ...overridesMarkdown
875
956
  }
@@ -878,6 +959,7 @@ async function markdown(options = {}) {
878
959
  files,
879
960
  name: "eslint/markdown/disables/markdown",
880
961
  rules: {
962
+ /** Disable rules do not work with markdown sourcecode. */
881
963
  "command/command": "off",
882
964
  "no-irregular-whitespace": "off",
883
965
  "perfectionist/sort-exports": "off",
@@ -1040,7 +1122,7 @@ async function perfectionist(options = {}) {
1040
1122
  async function detectCatalogUsage() {
1041
1123
  const workspaceFile = await findUp("pnpm-workspace.yaml");
1042
1124
  if (!workspaceFile) return false;
1043
- const yaml = await fs.readFile(workspaceFile, "utf-8");
1125
+ const yaml = await fsPromises.readFile(workspaceFile, "utf-8");
1044
1126
  return yaml.includes("catalog:") || yaml.includes("catalogs:");
1045
1127
  }
1046
1128
  async function pnpm(options) {
@@ -1049,7 +1131,7 @@ async function pnpm(options) {
1049
1131
  interopDefault(import("eslint-plugin-yml")),
1050
1132
  interopDefault(import("yaml-eslint-parser"))
1051
1133
  ]);
1052
- const { catalogs = await detectCatalogUsage(), isInEditor = false, json = true, sort = true, yaml = true } = options;
1134
+ const { catalogs = await detectCatalogUsage(), isInEditor = false, json = true, sort = true, stylistic = true, yaml = true } = options;
1053
1135
  const configs = [];
1054
1136
  if (json) configs.push({
1055
1137
  files: ["package.json", "**/package.json"],
@@ -1065,100 +1147,230 @@ async function pnpm(options) {
1065
1147
  "pnpm/json-valid-catalog": ["error", { autofix: !isInEditor }]
1066
1148
  }
1067
1149
  });
1068
- if (yaml) {
1069
- configs.push({
1070
- files: ["pnpm-workspace.yaml"],
1071
- languageOptions: { parser: yamlParser },
1072
- name: "eslint/pnpm/pnpm-workspace-yaml",
1073
- plugins: { pnpm: pluginPnpm },
1074
- rules: {
1075
- "pnpm/yaml-enforce-settings": ["error", { settings: {
1076
- shellEmulator: true,
1077
- trustPolicy: "no-downgrade"
1078
- } }],
1079
- "pnpm/yaml-no-duplicate-catalog-item": "error",
1080
- "pnpm/yaml-no-unused-catalog-item": "error"
1081
- }
1082
- });
1083
- if (sort) configs.push({
1084
- files: ["pnpm-workspace.yaml"],
1085
- languageOptions: { parser: yamlParser },
1086
- name: "eslint/pnpm/pnpm-workspace-yaml-sort",
1087
- plugins: { yaml: pluginYaml },
1088
- rules: { "yaml/sort-keys": [
1089
- "error",
1090
- {
1091
- order: [
1092
- ...[
1093
- "cacheDir",
1094
- "catalogMode",
1095
- "cleanupUnusedCatalogs",
1096
- "dedupeDirectDeps",
1097
- "deployAllFiles",
1098
- "enablePrePostScripts",
1099
- "engineStrict",
1100
- "extendNodePath",
1101
- "hoist",
1102
- "hoistPattern",
1103
- "hoistWorkspacePackages",
1104
- "ignoreCompatibilityDb",
1105
- "ignoreDepScripts",
1106
- "ignoreScripts",
1107
- "ignoreWorkspaceRootCheck",
1108
- "managePackageManagerVersions",
1109
- "minimumReleaseAge",
1110
- "minimumReleaseAgeExclude",
1111
- "modulesDir",
1112
- "nodeLinker",
1113
- "nodeVersion",
1114
- "optimisticRepeatInstall",
1115
- "packageManagerStrict",
1116
- "packageManagerStrictVersion",
1117
- "preferSymlinkedExecutables",
1118
- "preferWorkspacePackages",
1119
- "publicHoistPattern",
1120
- "registrySupportsTimeField",
1121
- "requiredScripts",
1122
- "resolutionMode",
1123
- "savePrefix",
1124
- "scriptShell",
1125
- "shamefullyHoist",
1126
- "shellEmulator",
1127
- "stateDir",
1128
- "supportedArchitectures",
1129
- "symlink",
1130
- "tag",
1131
- "trustPolicy",
1132
- "trustPolicyExclude",
1133
- "updateNotifier"
1134
- ],
1135
- "packages",
1136
- "overrides",
1137
- "patchedDependencies",
1138
- "catalog",
1139
- "catalogs",
1140
- ...[
1141
- "allowedDeprecatedVersions",
1142
- "allowNonAppliedPatches",
1143
- "configDependencies",
1144
- "ignoredBuiltDependencies",
1145
- "ignoredOptionalDependencies",
1146
- "neverBuiltDependencies",
1147
- "onlyBuiltDependencies",
1148
- "onlyBuiltDependenciesFile",
1149
- "packageExtensions",
1150
- "peerDependencyRules"
1151
- ]
1150
+ if (yaml) configs.push({
1151
+ files: ["pnpm-workspace.yaml"],
1152
+ languageOptions: { parser: yamlParser },
1153
+ name: "eslint/pnpm/pnpm-workspace-yaml",
1154
+ plugins: { pnpm: pluginPnpm },
1155
+ rules: {
1156
+ "pnpm/yaml-enforce-settings": ["error", { settings: {
1157
+ minimumReleaseAgeExcludePrune: true,
1158
+ shellEmulator: true
1159
+ } }],
1160
+ "pnpm/yaml-no-duplicate-catalog-item": "error",
1161
+ "pnpm/yaml-no-unused-catalog-item": "error"
1162
+ }
1163
+ });
1164
+ if (yaml && stylistic) configs.push({
1165
+ files: ["pnpm-workspace.yaml"],
1166
+ languageOptions: { parser: yamlParser },
1167
+ name: "antfu/pnpm/pnpm-workspace-yaml-stylistic",
1168
+ plugins: { pnpm: pluginPnpm },
1169
+ rules: { "pnpm/yaml-blank-lines": "error" }
1170
+ });
1171
+ if (yaml && sort) configs.push({
1172
+ files: ["pnpm-workspace.yaml"],
1173
+ languageOptions: { parser: yamlParser },
1174
+ name: "eslint/pnpm/pnpm-workspace-yaml-sort",
1175
+ plugins: { yaml: pluginYaml },
1176
+ rules: { "yaml/sort-keys": [
1177
+ "error",
1178
+ {
1179
+ order: [
1180
+ ...[
1181
+ "dedupeInjectedDeps",
1182
+ "disallowWorkspaceCycles",
1183
+ "failIfNoMatch",
1184
+ "ignoreWorkspaceCycles",
1185
+ "ignoreWorkspaceRootCheck",
1186
+ "includeWorkspaceRoot",
1187
+ "injectWorkspacePackages",
1188
+ "legacyDirFiltering",
1189
+ "linkWorkspacePackages",
1190
+ "preferWorkspacePackages",
1191
+ "saveWorkspaceProtocol",
1192
+ "sharedWorkspaceLockfile",
1193
+ "syncInjectedDepsAfterScripts"
1152
1194
  ],
1153
- pathPattern: "^$"
1154
- },
1155
- {
1156
- order: { type: "asc" },
1157
- pathPattern: ".*"
1158
- }
1159
- ] }
1160
- });
1161
- }
1195
+ ...[
1196
+ "catalogMode",
1197
+ "catalogPrune",
1198
+ "cleanupUnusedCatalogs"
1199
+ ],
1200
+ ...[
1201
+ "allowedDeprecatedVersions",
1202
+ "blockExoticSubdeps",
1203
+ "ignoredOptionalDependencies",
1204
+ "minimumReleaseAge",
1205
+ "minimumReleaseAgeExclude",
1206
+ "minimumReleaseAgeExcludePrune",
1207
+ "minimumReleaseAgeIgnoreMissingTime",
1208
+ "minimumReleaseAgeStrict",
1209
+ "registrySupportsTimeField",
1210
+ "resolutionMode",
1211
+ "supportedArchitectures",
1212
+ "trustLockfile",
1213
+ "trustPolicy",
1214
+ "trustPolicyExclude",
1215
+ "trustPolicyIgnoreAfter",
1216
+ "update"
1217
+ ],
1218
+ ...[
1219
+ "autoInstallPeers",
1220
+ "dedupePeerDependents",
1221
+ "dedupePeers",
1222
+ "peerDependencyRules",
1223
+ "resolvePeersFromWorkspaceRoot",
1224
+ "strictPeerDependencies"
1225
+ ],
1226
+ ...[
1227
+ "fetchMinSpeedKiBps",
1228
+ "fetchRetries",
1229
+ "fetchRetryFactor",
1230
+ "fetchRetryMaxtimeout",
1231
+ "fetchRetryMintimeout",
1232
+ "fetchTimeout",
1233
+ "fetchWarnTimeoutMs",
1234
+ "gitShallowHosts",
1235
+ "httpProxy",
1236
+ "httpsProxy",
1237
+ "localAddress",
1238
+ "maxsockets",
1239
+ "namedRegistries",
1240
+ "networkConcurrency",
1241
+ "noProxy",
1242
+ "registries",
1243
+ "registry",
1244
+ "strictSsl"
1245
+ ],
1246
+ ...[
1247
+ "dlxCacheMaxAge",
1248
+ "enableGlobalVirtualStore",
1249
+ "enableModulesDir",
1250
+ "extendNodePath",
1251
+ "modulesCacheMaxAge",
1252
+ "modulesDir",
1253
+ "nodeExperimentalPackageMap",
1254
+ "nodeLinker",
1255
+ "nodePackageMapType",
1256
+ "packageImportMethod",
1257
+ "preferSymlinkedExecutables",
1258
+ "symlink",
1259
+ "virtualStoreDir",
1260
+ "virtualStoreDirMaxLength",
1261
+ "virtualStoreOnly",
1262
+ "virtualStoreType"
1263
+ ],
1264
+ ...[
1265
+ "hoist",
1266
+ "hoistingLimits",
1267
+ "hoistPattern",
1268
+ "hoistWorkspacePackages",
1269
+ "publicHoistPattern",
1270
+ "shamefullyHoist"
1271
+ ],
1272
+ ...[
1273
+ "frozenStore",
1274
+ "storeDir",
1275
+ "strictStorePkgContentCheck",
1276
+ "useRunningStoreServer",
1277
+ "verifyStoreIntegrity"
1278
+ ],
1279
+ ...[
1280
+ "gitBranchLockfile",
1281
+ "lockfile",
1282
+ "lockfileIncludeTarballUrl",
1283
+ "mergeGitBranchLockfilesBranchPattern",
1284
+ "peersSuffixMaxLength",
1285
+ "preferFrozenLockfile"
1286
+ ],
1287
+ ...[
1288
+ "childConcurrency",
1289
+ "dangerouslyAllowAllBuilds",
1290
+ "enablePrePostScripts",
1291
+ "ignoreDepScripts",
1292
+ "ignoreScripts",
1293
+ "nodeOptions",
1294
+ "requiredScripts",
1295
+ "scriptShell",
1296
+ "shellEmulator",
1297
+ "sideEffectsCache",
1298
+ "sideEffectsCacheReadonly",
1299
+ "strictDepBuilds",
1300
+ "unsafePerm",
1301
+ "verifyDepsBeforeRun"
1302
+ ],
1303
+ ...[
1304
+ "managePackageManagerVersions",
1305
+ "nodeDownloadMirrors",
1306
+ "nodeVersion",
1307
+ "packageManagerStrict",
1308
+ "packageManagerStrictVersion",
1309
+ "pmOnFail",
1310
+ "runtimeOnFail"
1311
+ ],
1312
+ ...[
1313
+ "ci",
1314
+ "color",
1315
+ "engineStrict",
1316
+ "loglevel",
1317
+ "npmPath",
1318
+ "recursiveInstall",
1319
+ "updateNotifier",
1320
+ "useBetaCli",
1321
+ "useStderr"
1322
+ ],
1323
+ ...[
1324
+ "cacheDir",
1325
+ "globalBinDir",
1326
+ "globalDir",
1327
+ "globalPnpmfile",
1328
+ "globalShims",
1329
+ "ignorePnpmfile",
1330
+ "npmrcAuthFile",
1331
+ "pnpmfile",
1332
+ "stateDir"
1333
+ ],
1334
+ ...["audit", "versioning"],
1335
+ ...[
1336
+ "allowNonAppliedPatches",
1337
+ "dedupeDirectDeps",
1338
+ "deployAllFiles",
1339
+ "ignoreCompatibilityDb",
1340
+ "initAuthorEmail",
1341
+ "initAuthorName",
1342
+ "initAuthorUrl",
1343
+ "initLicense",
1344
+ "initVersion",
1345
+ "optimisticRepeatInstall",
1346
+ "saveExact",
1347
+ "savePrefix",
1348
+ "tag"
1349
+ ],
1350
+ "packages",
1351
+ "packageConfigs",
1352
+ "overrides",
1353
+ "packageExtensions",
1354
+ "patchedDependencies",
1355
+ "configDependencies",
1356
+ "allowBuilds",
1357
+ ...[
1358
+ "ignoredBuiltDependencies",
1359
+ "neverBuiltDependencies",
1360
+ "onlyBuiltDependencies",
1361
+ "onlyBuiltDependenciesFile"
1362
+ ],
1363
+ "catalog",
1364
+ "catalogs"
1365
+ ],
1366
+ pathPattern: "^$"
1367
+ },
1368
+ {
1369
+ order: { type: "asc" },
1370
+ pathPattern: ".*"
1371
+ }
1372
+ ] }
1373
+ });
1162
1374
  return configs;
1163
1375
  }
1164
1376
  //#endregion
@@ -1187,17 +1399,12 @@ async function react(options = {}) {
1187
1399
  const isUsingRemix = RemixPackages.some((i) => isPackageExists(i));
1188
1400
  const isUsingReactRouter = ReactRouterPackages.some((i) => isPackageExists(i));
1189
1401
  const isUsingNext = NextJsPackages.some((i) => isPackageExists(i));
1190
- const plugins = pluginReact.configs.all.plugins;
1191
1402
  return [
1192
1403
  {
1193
1404
  name: "eslint/react/setup",
1194
1405
  plugins: {
1195
- "react": plugins["@eslint-react"],
1196
- "react-dom": plugins["@eslint-react/dom"],
1197
- "react-naming-convention": plugins["@eslint-react/naming-convention"],
1198
- "react-refresh": pluginReactRefresh,
1199
- "react-rsc": plugins["@eslint-react/rsc"],
1200
- "react-web-api": plugins["@eslint-react/web-api"]
1406
+ "react": pluginReact.configs.all.plugins["@eslint-react"],
1407
+ "react-refresh": pluginReactRefresh
1201
1408
  }
1202
1409
  },
1203
1410
  {
@@ -1209,6 +1416,7 @@ async function react(options = {}) {
1209
1416
  name: "eslint/react/rules",
1210
1417
  rules: {
1211
1418
  ...pluginReact.configs.recommended.rules,
1419
+ /** preconfigured rules from eslint-plugin-react-refresh https://github.com/ArnaudBarre/eslint-plugin-react-refresh/tree/main/src */
1212
1420
  "react-refresh/only-export-components": ["error", {
1213
1421
  allowConstantExport: isAllowConstantExport,
1214
1422
  allowExportNames: [...isUsingNext ? [
@@ -1238,7 +1446,6 @@ async function react(options = {}) {
1238
1446
  "shouldRevalidate"
1239
1447
  ] : []]
1240
1448
  }],
1241
- "react/prefer-namespace-import": "error",
1242
1449
  ...overrides
1243
1450
  }
1244
1451
  },
@@ -1246,8 +1453,9 @@ async function react(options = {}) {
1246
1453
  files: filesTypeAware,
1247
1454
  name: "eslint/react/typescript",
1248
1455
  rules: {
1249
- "react-dom/no-string-style-prop": "off",
1250
- "react-dom/no-unknown-property": "off"
1456
+ /** Disables rules that are already handled by TypeScript */
1457
+ "react/dom-no-string-style-prop": "off",
1458
+ "react/dom-no-unknown-property": "off"
1251
1459
  }
1252
1460
  },
1253
1461
  ...isTypeAware ? [{
@@ -1328,6 +1536,7 @@ async function sortPackageJson() {
1328
1536
  "activationEvents",
1329
1537
  "contributes",
1330
1538
  "scripts",
1539
+ "scripts-info",
1331
1540
  "peerDependencies",
1332
1541
  "peerDependenciesMeta",
1333
1542
  "dependencies",
@@ -1643,6 +1852,7 @@ async function typescript(options = {}) {
1643
1852
  }
1644
1853
  return [
1645
1854
  {
1855
+ /** Install the plugins without globs, so they can be configured separately. */
1646
1856
  name: "eslint/typescript/setup",
1647
1857
  plugins: {
1648
1858
  antfu: pluginAntfu,
@@ -1680,8 +1890,11 @@ async function typescript(options = {}) {
1680
1890
  "ts/no-redeclare": ["error", { builtinGlobals: false }],
1681
1891
  "ts/no-require-imports": "error",
1682
1892
  "ts/no-unused-expressions": ["error", {
1893
+ /** allowShortCircuit 设置为 true 将允许你在表达式中使用短路计算(默认值:false) */
1683
1894
  allowShortCircuit: true,
1895
+ /** allowTaggedTemplates 设置为 true 将使你能够在表达式中使用标记模板字面量(默认值:false) */
1684
1896
  allowTaggedTemplates: true,
1897
+ /** allowTernary 设置为 true 将使你能够在表达式中使用三元运算符,类似于短路计算(默认值:false) */
1685
1898
  allowTernary: true
1686
1899
  }],
1687
1900
  "ts/no-unused-vars": ["warn", {
@@ -1725,6 +1938,7 @@ async function typescript(options = {}) {
1725
1938
  plugins: { "erasable-syntax-only": await interopDefault(import("eslint-plugin-erasable-syntax-only")) },
1726
1939
  rules: {
1727
1940
  "erasable-syntax-only/enums": "error",
1941
+ "erasable-syntax-only/export-aliases": "error",
1728
1942
  "erasable-syntax-only/import-aliases": "error",
1729
1943
  "erasable-syntax-only/namespaces": "error",
1730
1944
  "erasable-syntax-only/parameter-properties": "error"
@@ -1737,8 +1951,11 @@ async function typescript(options = {}) {
1737
1951
  async function unicorn(options = {}) {
1738
1952
  const { allRecommended = false, overrides = {} } = options;
1739
1953
  return [{
1740
- name: "eslint/unicorn/rules",
1741
- plugins: { unicorn: pluginUnicorn },
1954
+ name: "eslint/unicorn/setup",
1955
+ plugins: { unicorn: pluginUnicorn }
1956
+ }, {
1957
+ files: [GLOB_SRC],
1958
+ name: "antfu/unicorn/rules",
1742
1959
  rules: {
1743
1960
  ...allRecommended ? pluginUnicorn.configs.recommended.rules : {
1744
1961
  "unicorn/consistent-empty-array-spread": "error",
@@ -1787,13 +2004,17 @@ vueVersion = Number.isNaN(vueVersion) ? "3" : vueVersion;
1787
2004
  async function vue(options = {}) {
1788
2005
  const { files = [GLOB_VUE], overrides = {}, stylistic = true } = options;
1789
2006
  const sfcBlocks = options.sfcBlocks === true ? {} : options.sfcBlocks ?? {};
1790
- const { indent = 4 } = typeof stylistic === "boolean" ? {} : stylistic;
2007
+ const { braceStyle = "stroustrup", indent = 4 } = typeof stylistic === "boolean" ? {} : stylistic;
1791
2008
  const [pluginVue, parserVue, processorVueBlocks] = await Promise.all([
1792
2009
  interopDefault(import("eslint-plugin-vue")),
1793
2010
  interopDefault(import("vue-eslint-parser")),
1794
2011
  interopDefault(import("eslint-processor-vue-blocks"))
1795
2012
  ]);
1796
2013
  return [{
2014
+ /**
2015
+ * This allows Vue plugin to work with auto imports
2016
+ * https://github.com/vuejs/eslint-plugin-vue/pull/2422
2017
+ */
1797
2018
  languageOptions: { globals: {
1798
2019
  computed: "readonly",
1799
2020
  defineEmits: "readonly",
@@ -1953,7 +2174,7 @@ async function vue(options = {}) {
1953
2174
  }],
1954
2175
  "vue/brace-style": [
1955
2176
  "error",
1956
- "stroustrup",
2177
+ braceStyle,
1957
2178
  { allowSingleLine: false }
1958
2179
  ],
1959
2180
  "vue/comma-dangle": ["error", "always-multiline"],
@@ -2019,6 +2240,11 @@ async function yaml(options = {}) {
2019
2240
  "yaml/flow-sequence-bracket-spacing": "error",
2020
2241
  "yaml/indent": ["error", typeof other_indent === "number" ? other_indent : 2],
2021
2242
  "yaml/key-spacing": "error",
2243
+ "yaml/no-multiple-empty-lines": ["error", {
2244
+ max: 1,
2245
+ maxBOF: 0,
2246
+ maxEOF: 0
2247
+ }],
2022
2248
  "yaml/no-tab-indent": "error",
2023
2249
  "yaml/quotes": ["error", {
2024
2250
  avoidEscape: true,
@@ -2049,10 +2275,6 @@ const VuePackages = [
2049
2275
  ];
2050
2276
  const defaultPluginRenaming = {
2051
2277
  "@eslint-react": "react",
2052
- "@eslint-react/dom": "react-dom",
2053
- "@eslint-react/naming-convention": "react-naming-convention",
2054
- "@eslint-react/rsc": "react-rsc",
2055
- "@eslint-react/web-api": "react-web-api",
2056
2278
  "@next/next": "next",
2057
2279
  "@stylistic": "style",
2058
2280
  "@typescript-eslint": "ts",
@@ -2072,7 +2294,7 @@ const defaultPluginRenaming = {
2072
2294
  * 合并的 ESLint 配置
2073
2295
  */
2074
2296
  function lincy(options = {}, ...userConfigs) {
2075
- const { autoRenamePlugins = true, componentExts = [], e18e: enableE18e = true, gitignore: enableGitignore = true, ignores: userIgnores = [], imports: enableImports = true, jsx: enableJsx = true, nextjs: enableNextjs = false, overrides = {}, pnpm: enableCatalogs = !!findUpSync("pnpm-workspace.yaml"), react: enableReact = false, regexp: enableRegexp = true, type: appType = "app", typescript: enableTypeScript = isPackageExists("typescript") || isPackageExists("@typescript/native-preview"), unicorn: enableUnicorn = true, unocss: enableUnoCSS = false, vue: enableVue = VuePackages.some((i) => isPackageExists(i)) } = options;
2297
+ const { antislop: enableAntislop = false, autoRenamePlugins = true, componentExts = [], e18e: enableE18e = true, gitignore: enableGitignore = true, ignores: userIgnores = [], imports: enableImports = true, jsx: enableJsx = true, nextjs: enableNextjs = false, overrides = {}, pnpm: enableCatalogs = !!findUpSync("pnpm-workspace.yaml"), react: enableReact = false, regexp: enableRegexp = true, type: appType = "app", typescript: enableTypeScript = isPackageExists("typescript") || isPackageExists("@typescript/native-preview"), unicorn: enableUnicorn = true, unocss: enableUnoCSS = false, vue: enableVue = VuePackages.some((i) => isPackageExists(i)) } = options;
2076
2298
  let isInEditor = options.isInEditor;
2077
2299
  if (isInEditor == null) {
2078
2300
  isInEditor = isInEditorEnv();
@@ -2081,14 +2303,16 @@ function lincy(options = {}, ...userConfigs) {
2081
2303
  const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
2082
2304
  if (stylisticOptions && !("jsx" in stylisticOptions)) stylisticOptions.jsx = enableJsx;
2083
2305
  const configs = [];
2084
- if (enableGitignore) if (typeof enableGitignore !== "boolean") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2085
- name: "eslint/gitignore",
2086
- ...enableGitignore
2087
- })]));
2088
- else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2089
- name: "eslint/gitignore",
2090
- strict: false
2091
- })]));
2306
+ if (enableGitignore) {
2307
+ if (typeof enableGitignore !== "boolean") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2308
+ name: "eslint/gitignore",
2309
+ ...enableGitignore
2310
+ })]));
2311
+ else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2312
+ name: "eslint/gitignore",
2313
+ strict: false
2314
+ })]));
2315
+ }
2092
2316
  const typescriptOptions = resolveSubOptions(options, "typescript");
2093
2317
  const tsconfigPath = "tsconfigPath" in typescriptOptions ? typescriptOptions.tsconfigPath : void 0;
2094
2318
  configs.push(ignores([...overrides.ignores || [], ...userIgnores], !enableTypeScript), javascript({
@@ -2119,6 +2343,11 @@ function lincy(options = {}, ...userConfigs) {
2119
2343
  tsconfigPath,
2120
2344
  type: appType
2121
2345
  }));
2346
+ if (enableAntislop) configs.push(antislop({
2347
+ ...resolveSubOptions(options, "antislop"),
2348
+ overrides: getOverrides(options, "antislop"),
2349
+ typescript: !!enableTypeScript
2350
+ }));
2122
2351
  if (stylisticOptions) configs.push(stylistic({
2123
2352
  overrides: getOverrides(options, "stylistic"),
2124
2353
  stylistic: stylisticOptions
@@ -2156,6 +2385,9 @@ function lincy(options = {}, ...userConfigs) {
2156
2385
  }), sortPackageJson(), sortTsconfig());
2157
2386
  if (enableCatalogs) configs.push(pnpm({
2158
2387
  isInEditor,
2388
+ json: options.jsonc !== false,
2389
+ stylistic: stylisticOptions,
2390
+ yaml: options.yaml !== false,
2159
2391
  ...resolveSubOptions(options, "pnpm")
2160
2392
  }));
2161
2393
  if (options.yaml ?? true) configs.push(yaml({
@@ -2204,4 +2436,4 @@ function getOverrides(options, key) {
2204
2436
  //#region src/index.ts
2205
2437
  var src_default = lincy;
2206
2438
  //#endregion
2207
- export { GLOB_ALL_SRC, GLOB_CSS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_SVG, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_XML, GLOB_YAML, StylisticConfigDefaults, combine, comments, src_default as default, defaultPluginRenaming, disables, e18e, ensurePackages, formatters, getOverrides, ignores, imports, interopDefault, isInEditorEnv, isInGitHooksOrLintStaged, isPackageInScope, javascript, jsdoc, jsonc, jsx, lincy, markdown, nextjs, node, parserPlain, perfectionist, pnpm, react, regexp, renamePluginInConfigs, renameRules, resolveSubOptions, sortPackageJson, sortTsconfig, stylistic, test, toArray, toml, typescript, unicorn, unocss, vue, yaml };
2439
+ export { GLOB_ALL_SRC, GLOB_CSS, GLOB_EXCLUDE, GLOB_GRAPHQL, GLOB_HTML, GLOB_JS, GLOB_JSON, GLOB_JSON5, GLOB_JSONC, GLOB_JSX, GLOB_LESS, GLOB_MARKDOWN, GLOB_MARKDOWN_CODE, GLOB_MARKDOWN_IN_MARKDOWN, GLOB_POSTCSS, GLOB_SCSS, GLOB_SRC, GLOB_SRC_EXT, GLOB_STYLE, GLOB_SVG, GLOB_TESTS, GLOB_TOML, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_XML, GLOB_YAML, StylisticConfigDefaults, antislop, combine, comments, src_default as default, defaultPluginRenaming, disables, e18e, ensurePackages, formatters, getOverrides, ignores, imports, interopDefault, isInEditorEnv, isInGitHooksOrLintStaged, isPackageInScope, javascript, jsdoc, jsonc, jsx, lincy, markdown, nextjs, node, parserPlain, perfectionist, pnpm, react, regexp, renamePluginInConfigs, renameRules, resolveSubOptions, sortPackageJson, sortTsconfig, stylistic, test, toArray, toml, typescript, unicorn, unocss, vue, yaml };