@lincy/eslint-config 7.2.0 → 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,76 +365,6 @@ 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 = {
298
370
  braceStyle: "stroustrup",
@@ -568,6 +640,7 @@ async function javascript(options = {}) {
568
640
  "no-class-assign": "error",
569
641
  "no-compare-neg-zero": "error",
570
642
  "no-cond-assign": ["error", "always"],
643
+ /** 'no-console': ['error', { allow: ['warn', 'error'] }], */
571
644
  "no-console": "off",
572
645
  "no-const-assign": "error",
573
646
  "no-control-regex": "error",
@@ -859,6 +932,11 @@ async function markdown(options = {}) {
859
932
  files,
860
933
  ignores: [GLOB_MARKDOWN_IN_MARKDOWN],
861
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
+ */
862
940
  processor: mergeProcessors([markdown.processors.markdown, processorPassThrough])
863
941
  },
864
942
  {
@@ -872,6 +950,7 @@ async function markdown(options = {}) {
872
950
  rules: {
873
951
  ...markdown.configs.recommended.at(0)?.rules,
874
952
  "markdown/fenced-code-language": "off",
953
+ /** https://github.com/eslint/markdown/issues/294 */
875
954
  "markdown/no-missing-label-refs": "off",
876
955
  ...overridesMarkdown
877
956
  }
@@ -880,6 +959,7 @@ async function markdown(options = {}) {
880
959
  files,
881
960
  name: "eslint/markdown/disables/markdown",
882
961
  rules: {
962
+ /** Disable rules do not work with markdown sourcecode. */
883
963
  "command/command": "off",
884
964
  "no-irregular-whitespace": "off",
885
965
  "perfectionist/sort-exports": "off",
@@ -1042,7 +1122,7 @@ async function perfectionist(options = {}) {
1042
1122
  async function detectCatalogUsage() {
1043
1123
  const workspaceFile = await findUp("pnpm-workspace.yaml");
1044
1124
  if (!workspaceFile) return false;
1045
- const yaml = await fs.readFile(workspaceFile, "utf-8");
1125
+ const yaml = await fsPromises.readFile(workspaceFile, "utf-8");
1046
1126
  return yaml.includes("catalog:") || yaml.includes("catalogs:");
1047
1127
  }
1048
1128
  async function pnpm(options) {
@@ -1051,7 +1131,7 @@ async function pnpm(options) {
1051
1131
  interopDefault(import("eslint-plugin-yml")),
1052
1132
  interopDefault(import("yaml-eslint-parser"))
1053
1133
  ]);
1054
- 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;
1055
1135
  const configs = [];
1056
1136
  if (json) configs.push({
1057
1137
  files: ["package.json", "**/package.json"],
@@ -1067,100 +1147,230 @@ async function pnpm(options) {
1067
1147
  "pnpm/json-valid-catalog": ["error", { autofix: !isInEditor }]
1068
1148
  }
1069
1149
  });
1070
- if (yaml) {
1071
- configs.push({
1072
- files: ["pnpm-workspace.yaml"],
1073
- languageOptions: { parser: yamlParser },
1074
- name: "eslint/pnpm/pnpm-workspace-yaml",
1075
- plugins: { pnpm: pluginPnpm },
1076
- rules: {
1077
- "pnpm/yaml-enforce-settings": ["error", { settings: {
1078
- shellEmulator: true,
1079
- trustPolicy: "no-downgrade"
1080
- } }],
1081
- "pnpm/yaml-no-duplicate-catalog-item": "error",
1082
- "pnpm/yaml-no-unused-catalog-item": "error"
1083
- }
1084
- });
1085
- if (sort) configs.push({
1086
- files: ["pnpm-workspace.yaml"],
1087
- languageOptions: { parser: yamlParser },
1088
- name: "eslint/pnpm/pnpm-workspace-yaml-sort",
1089
- plugins: { yaml: pluginYaml },
1090
- rules: { "yaml/sort-keys": [
1091
- "error",
1092
- {
1093
- order: [
1094
- ...[
1095
- "cacheDir",
1096
- "catalogMode",
1097
- "cleanupUnusedCatalogs",
1098
- "dedupeDirectDeps",
1099
- "deployAllFiles",
1100
- "enablePrePostScripts",
1101
- "engineStrict",
1102
- "extendNodePath",
1103
- "hoist",
1104
- "hoistPattern",
1105
- "hoistWorkspacePackages",
1106
- "ignoreCompatibilityDb",
1107
- "ignoreDepScripts",
1108
- "ignoreScripts",
1109
- "ignoreWorkspaceRootCheck",
1110
- "managePackageManagerVersions",
1111
- "minimumReleaseAge",
1112
- "minimumReleaseAgeExclude",
1113
- "modulesDir",
1114
- "nodeLinker",
1115
- "nodeVersion",
1116
- "optimisticRepeatInstall",
1117
- "packageManagerStrict",
1118
- "packageManagerStrictVersion",
1119
- "preferSymlinkedExecutables",
1120
- "preferWorkspacePackages",
1121
- "publicHoistPattern",
1122
- "registrySupportsTimeField",
1123
- "requiredScripts",
1124
- "resolutionMode",
1125
- "savePrefix",
1126
- "scriptShell",
1127
- "shamefullyHoist",
1128
- "shellEmulator",
1129
- "stateDir",
1130
- "supportedArchitectures",
1131
- "symlink",
1132
- "tag",
1133
- "trustPolicy",
1134
- "trustPolicyExclude",
1135
- "updateNotifier"
1136
- ],
1137
- "packages",
1138
- "overrides",
1139
- "patchedDependencies",
1140
- "catalog",
1141
- "catalogs",
1142
- ...[
1143
- "allowedDeprecatedVersions",
1144
- "allowNonAppliedPatches",
1145
- "configDependencies",
1146
- "ignoredBuiltDependencies",
1147
- "ignoredOptionalDependencies",
1148
- "neverBuiltDependencies",
1149
- "onlyBuiltDependencies",
1150
- "onlyBuiltDependenciesFile",
1151
- "packageExtensions",
1152
- "peerDependencyRules"
1153
- ]
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"
1154
1194
  ],
1155
- pathPattern: "^$"
1156
- },
1157
- {
1158
- order: { type: "asc" },
1159
- pathPattern: ".*"
1160
- }
1161
- ] }
1162
- });
1163
- }
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
+ });
1164
1374
  return configs;
1165
1375
  }
1166
1376
  //#endregion
@@ -1206,6 +1416,7 @@ async function react(options = {}) {
1206
1416
  name: "eslint/react/rules",
1207
1417
  rules: {
1208
1418
  ...pluginReact.configs.recommended.rules,
1419
+ /** preconfigured rules from eslint-plugin-react-refresh https://github.com/ArnaudBarre/eslint-plugin-react-refresh/tree/main/src */
1209
1420
  "react-refresh/only-export-components": ["error", {
1210
1421
  allowConstantExport: isAllowConstantExport,
1211
1422
  allowExportNames: [...isUsingNext ? [
@@ -1242,6 +1453,7 @@ async function react(options = {}) {
1242
1453
  files: filesTypeAware,
1243
1454
  name: "eslint/react/typescript",
1244
1455
  rules: {
1456
+ /** Disables rules that are already handled by TypeScript */
1245
1457
  "react/dom-no-string-style-prop": "off",
1246
1458
  "react/dom-no-unknown-property": "off"
1247
1459
  }
@@ -1324,6 +1536,7 @@ async function sortPackageJson() {
1324
1536
  "activationEvents",
1325
1537
  "contributes",
1326
1538
  "scripts",
1539
+ "scripts-info",
1327
1540
  "peerDependencies",
1328
1541
  "peerDependenciesMeta",
1329
1542
  "dependencies",
@@ -1639,6 +1852,7 @@ async function typescript(options = {}) {
1639
1852
  }
1640
1853
  return [
1641
1854
  {
1855
+ /** Install the plugins without globs, so they can be configured separately. */
1642
1856
  name: "eslint/typescript/setup",
1643
1857
  plugins: {
1644
1858
  antfu: pluginAntfu,
@@ -1676,8 +1890,11 @@ async function typescript(options = {}) {
1676
1890
  "ts/no-redeclare": ["error", { builtinGlobals: false }],
1677
1891
  "ts/no-require-imports": "error",
1678
1892
  "ts/no-unused-expressions": ["error", {
1893
+ /** allowShortCircuit 设置为 true 将允许你在表达式中使用短路计算(默认值:false) */
1679
1894
  allowShortCircuit: true,
1895
+ /** allowTaggedTemplates 设置为 true 将使你能够在表达式中使用标记模板字面量(默认值:false) */
1680
1896
  allowTaggedTemplates: true,
1897
+ /** allowTernary 设置为 true 将使你能够在表达式中使用三元运算符,类似于短路计算(默认值:false) */
1681
1898
  allowTernary: true
1682
1899
  }],
1683
1900
  "ts/no-unused-vars": ["warn", {
@@ -1721,6 +1938,7 @@ async function typescript(options = {}) {
1721
1938
  plugins: { "erasable-syntax-only": await interopDefault(import("eslint-plugin-erasable-syntax-only")) },
1722
1939
  rules: {
1723
1940
  "erasable-syntax-only/enums": "error",
1941
+ "erasable-syntax-only/export-aliases": "error",
1724
1942
  "erasable-syntax-only/import-aliases": "error",
1725
1943
  "erasable-syntax-only/namespaces": "error",
1726
1944
  "erasable-syntax-only/parameter-properties": "error"
@@ -1733,8 +1951,11 @@ async function typescript(options = {}) {
1733
1951
  async function unicorn(options = {}) {
1734
1952
  const { allRecommended = false, overrides = {} } = options;
1735
1953
  return [{
1736
- name: "eslint/unicorn/rules",
1737
- plugins: { unicorn: pluginUnicorn },
1954
+ name: "eslint/unicorn/setup",
1955
+ plugins: { unicorn: pluginUnicorn }
1956
+ }, {
1957
+ files: [GLOB_SRC],
1958
+ name: "antfu/unicorn/rules",
1738
1959
  rules: {
1739
1960
  ...allRecommended ? pluginUnicorn.configs.recommended.rules : {
1740
1961
  "unicorn/consistent-empty-array-spread": "error",
@@ -1790,6 +2011,10 @@ async function vue(options = {}) {
1790
2011
  interopDefault(import("eslint-processor-vue-blocks"))
1791
2012
  ]);
1792
2013
  return [{
2014
+ /**
2015
+ * This allows Vue plugin to work with auto imports
2016
+ * https://github.com/vuejs/eslint-plugin-vue/pull/2422
2017
+ */
1793
2018
  languageOptions: { globals: {
1794
2019
  computed: "readonly",
1795
2020
  defineEmits: "readonly",
@@ -2015,6 +2240,11 @@ async function yaml(options = {}) {
2015
2240
  "yaml/flow-sequence-bracket-spacing": "error",
2016
2241
  "yaml/indent": ["error", typeof other_indent === "number" ? other_indent : 2],
2017
2242
  "yaml/key-spacing": "error",
2243
+ "yaml/no-multiple-empty-lines": ["error", {
2244
+ max: 1,
2245
+ maxBOF: 0,
2246
+ maxEOF: 0
2247
+ }],
2018
2248
  "yaml/no-tab-indent": "error",
2019
2249
  "yaml/quotes": ["error", {
2020
2250
  avoidEscape: true,
@@ -2064,7 +2294,7 @@ const defaultPluginRenaming = {
2064
2294
  * 合并的 ESLint 配置
2065
2295
  */
2066
2296
  function lincy(options = {}, ...userConfigs) {
2067
- 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;
2068
2298
  let isInEditor = options.isInEditor;
2069
2299
  if (isInEditor == null) {
2070
2300
  isInEditor = isInEditorEnv();
@@ -2073,14 +2303,16 @@ function lincy(options = {}, ...userConfigs) {
2073
2303
  const stylisticOptions = options.stylistic === false ? false : typeof options.stylistic === "object" ? options.stylistic : {};
2074
2304
  if (stylisticOptions && !("jsx" in stylisticOptions)) stylisticOptions.jsx = enableJsx;
2075
2305
  const configs = [];
2076
- if (enableGitignore) if (typeof enableGitignore !== "boolean") configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2077
- name: "eslint/gitignore",
2078
- ...enableGitignore
2079
- })]));
2080
- else configs.push(interopDefault(import("eslint-config-flat-gitignore")).then((r) => [r({
2081
- name: "eslint/gitignore",
2082
- strict: false
2083
- })]));
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
+ }
2084
2316
  const typescriptOptions = resolveSubOptions(options, "typescript");
2085
2317
  const tsconfigPath = "tsconfigPath" in typescriptOptions ? typescriptOptions.tsconfigPath : void 0;
2086
2318
  configs.push(ignores([...overrides.ignores || [], ...userIgnores], !enableTypeScript), javascript({
@@ -2111,6 +2343,11 @@ function lincy(options = {}, ...userConfigs) {
2111
2343
  tsconfigPath,
2112
2344
  type: appType
2113
2345
  }));
2346
+ if (enableAntislop) configs.push(antislop({
2347
+ ...resolveSubOptions(options, "antislop"),
2348
+ overrides: getOverrides(options, "antislop"),
2349
+ typescript: !!enableTypeScript
2350
+ }));
2114
2351
  if (stylisticOptions) configs.push(stylistic({
2115
2352
  overrides: getOverrides(options, "stylistic"),
2116
2353
  stylistic: stylisticOptions
@@ -2148,6 +2385,9 @@ function lincy(options = {}, ...userConfigs) {
2148
2385
  }), sortPackageJson(), sortTsconfig());
2149
2386
  if (enableCatalogs) configs.push(pnpm({
2150
2387
  isInEditor,
2388
+ json: options.jsonc !== false,
2389
+ stylistic: stylisticOptions,
2390
+ yaml: options.yaml !== false,
2151
2391
  ...resolveSubOptions(options, "pnpm")
2152
2392
  }));
2153
2393
  if (options.yaml ?? true) configs.push(yaml({
@@ -2196,4 +2436,4 @@ function getOverrides(options, key) {
2196
2436
  //#region src/index.ts
2197
2437
  var src_default = lincy;
2198
2438
  //#endregion
2199
- 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 };