xo 1.1.1 → 1.2.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/cli.d.ts CHANGED
@@ -10,8 +10,9 @@ declare const cli: import("meow").Result<{
10
10
  space: {
11
11
  type: "string";
12
12
  };
13
- config: {
13
+ configPath: {
14
14
  type: "string";
15
+ aliases: string[];
15
16
  };
16
17
  quiet: {
17
18
  type: "boolean";
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ const cli = meow(`
21
21
  --config Path to a XO configuration file
22
22
  --semicolon Use semicolons [Default: true]
23
23
  --react Include React specific parsing and xo-react linting rules [Default: false]
24
- --prettier Format with prettier or turn off prettier conflicted rules when set to 'compat' [Default: false]
24
+ --prettier Format with prettier or turn off Prettier-conflicted rules when set to 'compat' [Default: false]
25
25
  --print-config Print the effective ESLint config for the given file
26
26
  --version Print XO version
27
27
  --open Open files with issues in your editor
@@ -52,8 +52,9 @@ const cli = meow(`
52
52
  space: {
53
53
  type: 'string',
54
54
  },
55
- config: {
55
+ configPath: {
56
56
  type: 'string',
57
+ aliases: ['config'],
57
58
  },
58
59
  quiet: {
59
60
  type: 'boolean',
@@ -108,6 +109,7 @@ const linterOptions = {
108
109
  cwd: (cliOptions.cwd && path.resolve(cliOptions.cwd)) ?? process.cwd(),
109
110
  quiet: cliOptions.quiet,
110
111
  ts: true,
112
+ configPath: cliOptions.configPath,
111
113
  };
112
114
  // Make data types for `options.space` match those of the API
113
115
  if (typeof cliOptions.space === 'string') {
@@ -25,9 +25,6 @@ export async function handleTsconfig({ cwd, files }) {
25
25
  unincludedFiles.push(filePath);
26
26
  }
27
27
  const fallbackTsConfigPath = path.join(cwd, 'node_modules', '.cache', cacheDirName, 'tsconfig.xo.json');
28
- delete tsConfig.include;
29
- delete tsConfig.exclude;
30
- delete tsConfig.files;
31
28
  tsConfig.files = unincludedFiles;
32
29
  if (unincludedFiles.length > 0) {
33
30
  try {
@@ -32,7 +32,9 @@ export async function resolveXoConfig(options) {
32
32
  });
33
33
  options.filePath &&= path.resolve(options.cwd, options.filePath);
34
34
  const searchPath = options.filePath ?? options.cwd;
35
- let { config: flatOptions = [], filepath: flatConfigPath = '', } = await flatConfigExplorer.search(searchPath) ?? {};
35
+ let { config: flatOptions = [], filepath: flatConfigPath = '', } = await (options.configPath
36
+ ? flatConfigExplorer.load(path.resolve(options.cwd, options.configPath))
37
+ : flatConfigExplorer.search(searchPath)) ?? {};
36
38
  flatOptions = arrify(flatOptions);
37
39
  return {
38
40
  flatOptions,
@@ -52,6 +52,10 @@ export type LinterOptions = {
52
52
  @private
53
53
  */
54
54
  ts?: boolean;
55
+ /**
56
+ Custom path to config to use for the linter.
57
+ */
58
+ configPath?: string;
55
59
  };
56
60
  export type LintTextOptions = {
57
61
  /**
@@ -1,5 +1,5 @@
1
- import { type SetRequired } from 'type-fest';
2
1
  import { type Linter } from 'eslint';
2
+ import { type SetRequired } from 'type-fest';
3
3
  import { type XoConfigItem } from './types.js';
4
4
  /**
5
5
  Convert a `xo` config item to an ESLint config item.
@@ -12,3 +12,26 @@ Files and rules will always be defined and all other ESLint config properties ar
12
12
  @returns eslintConfig
13
13
  */
14
14
  export declare const xoToEslintConfigItem: (xoConfig: XoConfigItem) => SetRequired<Linter.Config, "rules" | "files">;
15
+ /**
16
+ Function used to match files which should be included in the `tsconfig.json` files.
17
+
18
+ @param cwd - The current working directory to resolve relative filepaths.
19
+ @param files - The _absolute_ file paths to match against the globs.
20
+ @param globs - The globs to match the files against.
21
+ @param ignores - The globs to ignore when matching the files.
22
+ @returns An array of file paths that match the globs and do not match the ignores.
23
+ */
24
+ export declare const matchFilesForTsConfig: (cwd: string, files: string[], globs: string[], ignores: string[]) => string[];
25
+ /**
26
+ Once a config is resolved, it is pre-processed to ensure that all properties are set correctly.
27
+
28
+ This includes ensuring that user-defined properties can override XO defaults, and that files are parsed correctly and performantly based on the users XO config.
29
+
30
+ @param xoConfig - The flat XO config to pre-process.
31
+ @returns The pre-processed flat XO config.
32
+ */
33
+ export declare const preProcessXoConfig: (xoConfig: XoConfigItem[]) => {
34
+ config: XoConfigItem[];
35
+ tsFilesGlob: string[];
36
+ tsFilesIgnoresGlob: string[];
37
+ };
package/dist/lib/utils.js CHANGED
@@ -1,5 +1,8 @@
1
+ import path from 'node:path';
2
+ import micromatch from 'micromatch';
1
3
  import arrify from 'arrify';
2
- import { allFilesGlob } from './constants.js';
4
+ import configXoTypescript from 'eslint-config-xo-typescript';
5
+ import { allFilesGlob, jsExtensions, jsFilesGlob, } from './constants.js';
3
6
  /**
4
7
  Convert a `xo` config item to an ESLint config item.
5
8
 
@@ -20,4 +23,98 @@ export const xoToEslintConfigItem = (xoConfig) => {
20
23
  eslintConfig.ignores &&= arrify(xoConfig.ignores);
21
24
  return eslintConfig;
22
25
  };
26
+ /**
27
+ Function used to match files which should be included in the `tsconfig.json` files.
28
+
29
+ @param cwd - The current working directory to resolve relative filepaths.
30
+ @param files - The _absolute_ file paths to match against the globs.
31
+ @param globs - The globs to match the files against.
32
+ @param ignores - The globs to ignore when matching the files.
33
+ @returns An array of file paths that match the globs and do not match the ignores.
34
+ */
35
+ export const matchFilesForTsConfig = (cwd, files, globs, ignores) => micromatch(files.map(file => path.normalize(path.relative(cwd, file))),
36
+ // https://github.com/micromatch/micromatch/issues/217
37
+ globs.map(glob => path.normalize(glob)), {
38
+ dot: true,
39
+ ignore: ignores.map(file => path.normalize(file)),
40
+ cwd,
41
+ }).map(file => path.resolve(cwd, file));
42
+ /**
43
+ Once a config is resolved, it is pre-processed to ensure that all properties are set correctly.
44
+
45
+ This includes ensuring that user-defined properties can override XO defaults, and that files are parsed correctly and performantly based on the users XO config.
46
+
47
+ @param xoConfig - The flat XO config to pre-process.
48
+ @returns The pre-processed flat XO config.
49
+ */
50
+ export const preProcessXoConfig = (xoConfig) => {
51
+ const tsFilesGlob = [];
52
+ const tsFilesIgnoresGlob = [];
53
+ const processedConfig = [];
54
+ for (const [idx, { ...config }] of xoConfig.entries()) {
55
+ // We can skip the first config item, as it is the base config item.
56
+ if (idx === 0) {
57
+ processedConfig.push(config);
58
+ continue;
59
+ }
60
+ // Use TS parser/plugin for JS files if the config contains TypeScript rules which are applied to JS files.
61
+ // typescript-eslint rules set to "off" are ignored and not applied to JS files.
62
+ if (config.rules
63
+ && !config.languageOptions?.parser
64
+ && !config.languageOptions?.parserOptions?.['project']
65
+ && !config.plugins?.['@typescript-eslint']) {
66
+ const hasTsRules = Object.entries(config.rules).some(rulePair => {
67
+ // If its not a @typescript-eslint rule, we don't care
68
+ if (!rulePair[0].startsWith('@typescript-eslint/')) {
69
+ return false;
70
+ }
71
+ if (Array.isArray(rulePair[1])) {
72
+ return rulePair[1]?.[0] !== 'off' && rulePair[1]?.[0] !== 0;
73
+ }
74
+ return rulePair[1] !== 'off'
75
+ && rulePair[1] !== 0;
76
+ });
77
+ if (hasTsRules) {
78
+ let isAppliedToJsFiles = false;
79
+ if (config.files) {
80
+ const normalizedFiles = arrify(config.files).map(file => path.normalize(file));
81
+ // Strip the basename off any globs
82
+ const globs = normalizedFiles.map(file => micromatch.scan(file, { dot: true }).glob).filter(Boolean);
83
+ // Check if the files globs match a test file with a js extension
84
+ // If not, check that the file paths match a js extension
85
+ isAppliedToJsFiles = micromatch.some(jsExtensions.map(ext => `test.${ext}`), globs, { dot: true })
86
+ || micromatch.some(normalizedFiles, jsFilesGlob, { dot: true });
87
+ }
88
+ else if (config.files === undefined) {
89
+ isAppliedToJsFiles = true;
90
+ }
91
+ if (isAppliedToJsFiles) {
92
+ config.languageOptions ??= {};
93
+ config.plugins ??= {};
94
+ config.plugins = {
95
+ ...config.plugins,
96
+ ...configXoTypescript[1]?.plugins,
97
+ };
98
+ config.languageOptions.parser = configXoTypescript[1]?.languageOptions?.parser;
99
+ tsFilesGlob.push(...arrify(config.files ?? allFilesGlob));
100
+ tsFilesIgnoresGlob.push(...arrify(config.ignores));
101
+ }
102
+ }
103
+ }
104
+ // If a user sets the `parserOptions.project` or `projectService` or `tsconfigRootDir`, we need to ensure that the tsFilesGlob is set to exclude those files,
105
+ // as this indicates the user has opted out of the default TypeScript handling for those files.
106
+ if (config.languageOptions?.parserOptions?.['project'] !== undefined
107
+ || config.languageOptions?.parserOptions?.['projectService'] !== undefined
108
+ || config.languageOptions?.parserOptions?.['tsconfigRootDir'] !== undefined) {
109
+ // The glob itself should NOT be negated
110
+ tsFilesIgnoresGlob.push(...arrify(config.files ?? allFilesGlob));
111
+ }
112
+ processedConfig.push(config);
113
+ }
114
+ return {
115
+ config: processedConfig,
116
+ tsFilesGlob,
117
+ tsFilesIgnoresGlob,
118
+ };
119
+ };
23
120
  //# sourceMappingURL=utils.js.map
package/dist/lib/xo.d.ts CHANGED
@@ -48,13 +48,23 @@ export declare class Xo {
48
48
  */
49
49
  flatConfigPath?: string | undefined;
50
50
  /**
51
- If any user configs container Prettier, we will need to fetch the Prettier config.
51
+ If any user configs contains Prettier, we will need to fetch the Prettier config.
52
52
  */
53
53
  prettier?: boolean;
54
54
  /**
55
55
  The Prettier config if it exists and is needed.
56
56
  */
57
57
  prettierConfig?: prettier.Options;
58
+ /**
59
+ The glob pattern for TypeScript files, for which we will handle TS files and tsconfig.
60
+
61
+ We expand this based on the XO config and the files glob patterns.
62
+ */
63
+ tsFilesGlob: string[];
64
+ /**
65
+ We use this to also add negative glob patterns in case a user overrides the parserOptions in their XO config.
66
+ */
67
+ tsFilesIgnoresGlob: string[];
58
68
  constructor(_linterOptions: LinterOptions, _baseXoConfig?: XoConfigOptions);
59
69
  /**
60
70
  Sets the XO config on the XO instance.
package/dist/lib/xo.js CHANGED
@@ -6,13 +6,12 @@ import findCacheDirectory from 'find-cache-directory';
6
6
  import { globby } from 'globby';
7
7
  import arrify from 'arrify';
8
8
  import defineLazyProperty from 'define-lazy-prop';
9
- import micromatch from 'micromatch';
10
9
  import prettier from 'prettier';
11
- import { defaultIgnores, cacheDirName, allExtensions, tsFilesGlob, allFilesGlob, } from './constants.js';
10
+ import { defaultIgnores, cacheDirName, allExtensions, tsFilesGlob, } from './constants.js';
12
11
  import { xoToEslintConfig } from './xo-to-eslint.js';
13
12
  import resolveXoConfig from './resolve-config.js';
14
13
  import { handleTsconfig } from './handle-ts-files.js';
15
- // Import {handleTsconfig} from './handle-ts-files-typescript.js';
14
+ import { matchFilesForTsConfig, preProcessXoConfig } from './utils.js';
16
15
  export class Xo {
17
16
  /**
18
17
  Static helper to convert an XO config to an ESLint config to be used in `eslint.config.js`.
@@ -28,6 +27,7 @@ export class Xo {
28
27
  filePath: options.filePath,
29
28
  quiet: options.quiet,
30
29
  ts: options.ts ?? true,
30
+ configPath: options.configPath,
31
31
  }, {
32
32
  react: options.react,
33
33
  space: options.space,
@@ -50,6 +50,7 @@ export class Xo {
50
50
  filePath: options.filePath,
51
51
  quiet: options.quiet,
52
52
  ts: options.ts,
53
+ configPath: options.configPath,
53
54
  }, {
54
55
  react: options.react,
55
56
  space: options.space,
@@ -94,13 +95,23 @@ export class Xo {
94
95
  */
95
96
  flatConfigPath;
96
97
  /**
97
- If any user configs container Prettier, we will need to fetch the Prettier config.
98
+ If any user configs contains Prettier, we will need to fetch the Prettier config.
98
99
  */
99
100
  prettier;
100
101
  /**
101
102
  The Prettier config if it exists and is needed.
102
103
  */
103
104
  prettierConfig;
105
+ /**
106
+ The glob pattern for TypeScript files, for which we will handle TS files and tsconfig.
107
+
108
+ We expand this based on the XO config and the files glob patterns.
109
+ */
110
+ tsFilesGlob = [tsFilesGlob];
111
+ /**
112
+ We use this to also add negative glob patterns in case a user overrides the parserOptions in their XO config.
113
+ */
114
+ tsFilesIgnoresGlob = [];
104
115
  constructor(_linterOptions, _baseXoConfig = {}) {
105
116
  this.linterOptions = _linterOptions;
106
117
  this.baseXoConfig = _baseXoConfig;
@@ -123,53 +134,13 @@ export class Xo {
123
134
  const { flatOptions, flatConfigPath } = await resolveXoConfig({
124
135
  ...this.linterOptions,
125
136
  });
126
- this.xoConfig = [
137
+ const { config, tsFilesGlob, tsFilesIgnoresGlob } = preProcessXoConfig([
127
138
  this.baseXoConfig,
128
139
  ...flatOptions,
129
- ];
130
- // Split off the TS rules in a special case, so that you won't get errors
131
- // for JS files when the TS rules are not in the config.
132
- this.xoConfig = this.xoConfig.flatMap(config => {
133
- // If the user does not specify files, then we can assume they want everything to work correctly and
134
- // for rules to apply to all files. However, TS rules will error with JS files, so we need to split them off.
135
- // if the user supplies files, then we cannot make the same assumption, so we will not split them off.
136
- if (config.files) {
137
- return config;
138
- }
139
- const ruleEntries = Object.entries(config.rules ?? {});
140
- const otherRules = [];
141
- const tsRules = [];
142
- for (const [rule, ruleValue] of ruleEntries) {
143
- if (!rule || !ruleValue) {
144
- continue;
145
- }
146
- if (rule.startsWith('@typescript-eslint')) {
147
- tsRules.push([rule, ruleValue]);
148
- }
149
- else {
150
- otherRules.push([rule, ruleValue]);
151
- }
152
- }
153
- // If no TS rules, return the config as is
154
- if (tsRules.length === 0) {
155
- return config;
156
- }
157
- // If there are TS rules, we need to split them off into a new config
158
- const tsConfig = {
159
- ...config,
160
- rules: Object.fromEntries(tsRules),
161
- };
162
- // Apply TS rules to all files
163
- tsConfig.files = [tsFilesGlob];
164
- const otherConfig = {
165
- ...config,
166
- // Set the other rules to the original config
167
- rules: Object.fromEntries(otherRules),
168
- };
169
- // These rules should still apply to all files
170
- otherConfig.files = [allFilesGlob];
171
- return [tsConfig, otherConfig];
172
- });
140
+ ]);
141
+ this.xoConfig = config;
142
+ this.tsFilesGlob.push(...tsFilesGlob);
143
+ this.tsFilesIgnoresGlob.push(...tsFilesIgnoresGlob);
173
144
  this.prettier = this.xoConfig.some(config => config.prettier);
174
145
  this.prettierConfig = await prettier.resolveConfig(flatConfigPath, { editorconfig: true }) ?? {};
175
146
  this.flatConfigPath = flatConfigPath;
@@ -218,7 +189,7 @@ export class Xo {
218
189
  if (!this.linterOptions.ts || !files || files.length === 0) {
219
190
  return;
220
191
  }
221
- const tsFiles = files.filter(file => micromatch.isMatch(file, tsFilesGlob, { dot: true }));
192
+ const tsFiles = matchFilesForTsConfig(this.linterOptions.cwd, files, this.tsFilesGlob, this.tsFilesIgnoresGlob);
222
193
  if (tsFiles.length === 0) {
223
194
  return;
224
195
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xo",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "JavaScript/TypeScript linter (ESLint wrapper) with great defaults",
5
5
  "license": "MIT",
6
6
  "repository": "xojs/xo",
@@ -68,34 +68,34 @@
68
68
  "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0",
69
69
  "@sindresorhus/tsconfig": "^7.0.0",
70
70
  "@stylistic/eslint-plugin": "^4.2.0",
71
- "@typescript-eslint/parser": "^8.32.1",
71
+ "@typescript-eslint/parser": "^8.37.0",
72
72
  "arrify": "^3.0.0",
73
73
  "cosmiconfig": "^9.0.0",
74
74
  "define-lazy-prop": "^3.0.0",
75
- "eslint": "^9.27.0",
75
+ "eslint": "^9.31.0",
76
76
  "eslint-config-prettier": "^10.1.5",
77
77
  "eslint-config-xo-react": "^0.28.0",
78
78
  "eslint-config-xo-typescript": "^7.0.0",
79
79
  "eslint-formatter-pretty": "^6.0.1",
80
80
  "eslint-plugin-ava": "^15.0.1",
81
- "eslint-plugin-import-x": "^4.12.2",
82
- "eslint-plugin-n": "^17.18.0",
81
+ "eslint-plugin-import-x": "^4.16.1",
82
+ "eslint-plugin-n": "^17.21.0",
83
83
  "eslint-plugin-no-use-extend-native": "^0.7.2",
84
- "eslint-plugin-prettier": "^5.4.0",
84
+ "eslint-plugin-prettier": "^5.5.1",
85
85
  "eslint-plugin-promise": "^7.2.1",
86
86
  "eslint-plugin-unicorn": "^59.0.1",
87
87
  "find-cache-directory": "^6.0.0",
88
88
  "get-stdin": "^9.0.0",
89
89
  "get-tsconfig": "^4.10.1",
90
- "globals": "^16.1.0",
90
+ "globals": "^16.3.0",
91
91
  "globby": "^14.1.0",
92
92
  "meow": "^13.2.0",
93
93
  "micromatch": "^4.0.8",
94
94
  "open-editor": "^5.1.0",
95
95
  "path-exists": "^5.0.0",
96
- "prettier": "^3.5.3",
96
+ "prettier": "^3.6.2",
97
97
  "type-fest": "^4.41.0",
98
- "typescript-eslint": "^8.32.1"
98
+ "typescript-eslint": "^8.37.0"
99
99
  },
100
100
  "devDependencies": {
101
101
  "@commitlint/cli": "^19.8.1",
@@ -103,15 +103,15 @@
103
103
  "@types/eslint": "9.6.1",
104
104
  "@types/micromatch": "^4.0.9",
105
105
  "@types/prettier": "^3.0.0",
106
- "ava": "^6.3.0",
106
+ "ava": "^6.4.1",
107
107
  "dedent": "^1.6.0",
108
108
  "execa": "^9.5.3",
109
109
  "husky": "^9.1.7",
110
110
  "lint-staged": "^16.0.0",
111
111
  "np": "^10.2.0",
112
- "npm-package-json-lint": "^8.0.0",
113
- "npm-package-json-lint-config-default": "^7.0.1",
114
- "prettier-plugin-packagejson": "^2.5.14",
112
+ "npm-package-json-lint": "^9.0.0",
113
+ "npm-package-json-lint-config-default": "^8.0.1",
114
+ "prettier-plugin-packagejson": "^2.5.18",
115
115
  "temp-dir": "^3.0.0",
116
116
  "xo": "file:."
117
117
  },
@@ -133,7 +133,8 @@
133
133
  ".history/**/*",
134
134
  "node_modules",
135
135
  "package.json",
136
- "xo.config.*"
136
+ "xo.config.*",
137
+ "**/*.ts"
137
138
  ]
138
139
  }
139
140
  },
package/readme.md CHANGED
@@ -34,7 +34,7 @@ It uses [ESLint](https://eslint.org) underneath, so issues regarding built-in ru
34
34
  - Open all files with errors at the correct line in your editor with `$ xo --open`.
35
35
  - Specify [indent](#space) and [semicolon](#semicolon) preferences easily without messing with the rule config.
36
36
  - Optionally use the [Prettier](https://github.com/prettier/prettier) code style or turn off all Prettier rules with the `compat` option.
37
- - Optionally use `eslint-config-xo-react` for easy jsx and react linting with zero config.
37
+ - Optionally use `eslint-config-xo-react` for easy JSX and React linting with zero config.
38
38
  - Optionally use with ESLint [directly](#usage-as-an-eslint-configuration)
39
39
  - Great [editor plugins](#editor-plugins).
40
40
 
@@ -63,7 +63,7 @@ $ xo --help
63
63
  --config Path to a XO configuration file
64
64
  --semicolon Use semicolons [Default: true]
65
65
  --react Include React specific parsing and xo-react linting rules [Default: false]
66
- --prettier Format with prettier or turn off prettier conflicted rules when set to 'compat' [Default: false]
66
+ --prettier Format with prettier or turn off prettier-conflicted rules when set to 'compat' [Default: false]
67
67
  --print-config Print the effective ESLint config for the given file
68
68
  --version Print XO version
69
69
  --open Open files with issues in your editor
@@ -108,7 +108,7 @@ Simply run `$ npm init xo` (with any options) to add XO to create an `xo.config.
108
108
 
109
109
  ## Config
110
110
 
111
- You can configure XO options by creating an `xo.config.js` or an `xo.config.ts` file in the root directory of your project. XO supports all js/ts file extensions (js,cjs,mjs,ts,cts,mts) automatically. A XO config is an extension of ESLint's Flat Config. Like ESLint, an XO config exports an array of XO config objects. XO config objects extend [ESLint Configuration Objects](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-objects). This means all the available configuration params for ESLint also work for `XO`. However, `XO` enhances and adds extra params to the configuration objects to make them easier to work with.
111
+ You can configure XO options by creating an `xo.config.js` or an `xo.config.ts` file in the root directory of your project, or you can add an `xo` field to your `package.json`. XO supports all js/ts file extensions (js,cjs,mjs,ts,cts,mts) automatically. A XO config is an extension of ESLint's Flat Config. Like ESLint, an XO config exports an array of XO config objects. XO config objects extend [ESLint Configuration Objects](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-objects). This means all the available configuration params for ESLint also work for `XO`. However, `XO` enhances and adds extra params to the configuration objects to make them easier to work with.
112
112
 
113
113
  ### Config types
114
114
 
@@ -124,12 +124,16 @@ const xoConfig = [...]
124
124
 
125
125
  `xo.config.ts`
126
126
 
127
- ```js
127
+ ```ts
128
128
  import {type FlatXoConfig} from 'xo';
129
129
 
130
130
  const xoConfig: FlatXoConfig = [...]
131
131
  ```
132
132
 
133
+ ```ts
134
+ export default [...] satisfies import('xo').FlatXoConfig
135
+ ```
136
+
133
137
  ### files
134
138
 
135
139
  Type: `string | string[] | undefined`\
@@ -137,11 +141,15 @@ Default: `**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}`
137
141
 
138
142
  A glob or array of glob strings which the config object will apply. By default `XO` will apply the configuration to [all files](lib/constants.ts).
139
143
 
144
+ > Tip: If you are adding additional `@typescript-eslint` rules to your config, these rules will apply to JS files as well unless you separate them appropriately with the `files` option. `@typescript-eslint` rules set to `'off'` or `0`, however, will have no effect on JS linting.
145
+
140
146
  ### ignores
141
147
 
142
148
  Type: `string[]`
143
149
 
144
- Some [paths](lib/constants.ts) are ignored by default, including paths in `.gitignore`. Additional ignores can be added here. For global ignores, keep `ignores` as the only key in the config item.
150
+ Some [paths](lib/constants.ts) are ignored by default, including paths in `.gitignore`. Additional ignores can be added here.
151
+
152
+ > Tip: For *global* ignores, keep `ignores` as the only key in the config item. You can optionally set a `name` property. Adding more properties will cause ignores to be scoped down to your files selection, which may have unexpected effects.
145
153
 
146
154
  ### space
147
155
 
@@ -202,15 +210,17 @@ XO will automatically lint TypeScript files (`.ts`, `.mts`, `.cts`, and `.tsx`)
202
210
 
203
211
  XO will handle the [@typescript-eslint/parser `project` option](https://typescript-eslint.io/packages/parser/#project) automatically even if you don't have a `tsconfig.json` in your project.
204
212
 
213
+ You can opt out of XO's automatic tsconfig handling by specifying your own `languageOptions.parserOptions.project`, `languageOptions.parserOptions.projectService`, or `languageOptions.parserOptions.tsconfigRootDir`. Files in a config with these properties will be excluded from automatic tsconfig handling.
214
+
205
215
  ## Usage as an ESLint Configuration
206
216
 
207
217
  With the introduction of the ESLint flat config, many of the original goals of `xo` were brought into the ESLint core, and shareable configs with plugins became possible. Although we highly recommend the use of the `xo` cli, we understand that some teams need to rely on ESLint directly.
208
218
 
209
219
  For these purposes, you can still get most of the features of `xo` by using our ESLint configuration helpers.
210
220
 
211
- ### `xoToEslintConfig`
221
+ ### xoToEslintConfig
212
222
 
213
- The `xoToEslintConfig` function is designed for use in an `eslint.config.js` file. It is NOT for use in an `xo.config.js` file. This function takes a `FlatXoConfig` and outputs an ESLint config object. This function will neither be able to automatically handle TS integration for you nor automatic Prettier integration. You are responsible for configuring your other tools appropriately. The `xo` cli, will however, handle all of these details for you.
223
+ The `xoToEslintConfig` function is designed for use in an `eslint.config.js` file. It is NOT for use in an `xo.config.js` file. This function takes a `FlatXoConfig` and outputs an ESLint config object. This function will neither be able to automatically handle TS integration for you nor automatic Prettier integration. You are responsible for configuring your other tools appropriately. The `xo` cli, will, however, handle all of these details for you.
214
224
 
215
225
  `eslint.config.js`
216
226