Skip to content

Add support for ignoring native browserslist resolution #585

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ Add polyfills to the settings section of your eslint config. Append the name of
}
```

## Ignoring Browserslist native resolution

To exclude targets picked up by your browserslist config and only use targets explictly provided via ESLint:

```jsonc
{
// ...
"rules": {
"compat/compat": [ "error", {
"query": "node 18",
"ignoreBrowserslistTargets": true
} ]
}
}
```

## Linting ES APIs (Experimental)

This plugin also supports linting the compatibility of ES APIs in addition to Web APIs. This is an experimental feature and is disabled by default. To enable this feature, add the following to your eslint config:
Expand Down
39 changes: 20 additions & 19 deletions src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,31 +185,32 @@ export function determineTargetsFromConfig(
const browserslistOpts = { path: configPath };

const eslintTargets = (() => {
// Get targets from eslint settings
if (Array.isArray(config) || typeof config === "string") {
return browserslist(config, browserslistOpts);
}
if (config && typeof config === "object") {
return browserslist(
[...(config.production || []), ...(config.development || [])],
browserslistOpts
);
}
return [];
const query = config
? Array.isArray(config) || typeof config === "string"
? config
: "query" in config
? config.query
: [...(config.production || []), ...(config.development || [])]
: [];
return query.length ? browserslist(query, browserslistOpts) : [];
})();

if (browserslist.findConfig(configPath)) {
// If targets are defined in ESLint and browerslist configs, merge the targets together
if (eslintTargets.length) {
const browserslistTargets = browserslist(undefined, browserslistOpts);
return Array.from(new Set(eslintTargets.concat(browserslistTargets)));
}
} else if (eslintTargets.length) {
// Determine if targets picked up by browserslist should be included
const ignoreBrowserslistTargets =
config && "object" === typeof config && "query" in config
? Boolean(config.ignoreBrowserslistTargets)
: // Included for backwards-compatibility; remove in next major version (return false instead)
!browserslist.findConfig(configPath) && eslintTargets.length > 0;

if (ignoreBrowserslistTargets) {
return eslintTargets;
}

// Get targets fron browserslist configs
return browserslist(undefined, browserslistOpts);
const browserslistTargets = browserslist(undefined, browserslistOpts);

// If targets are defined in ESLint and browerslist configs, merge the targets together
return Array.from(new Set(eslintTargets.concat(browserslistTargets)));
}

/**
Expand Down
24 changes: 23 additions & 1 deletion src/rules/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,29 @@ export default {
recommended: true,
},
type: "problem",
schema: [{ type: "string" }],
schema: [
{
oneOf: [
{ type: "string" },
{
additionalProperties: false,
properties: {
ignoreBrowserslistTargets: {
type: "boolean",
},
query: {
oneOf: [
{ type: "string" },
{ items: { type: "string" }, type: "array" },
],
},
},
required: ["query"],
type: "object",
},
],
},
],
},
create(context: Context): ESLint {
// Determine lowest targets from browserslist config, which reads user's
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export type BrowserListConfig =
production?: Array<string>;
development?: Array<string>;
}
| {
ignoreBrowserslistTargets?: boolean;
query: string | Array<string>;
}
| null;

// @TODO Replace with types from ast-metadata-inferer
Expand Down
40 changes: 40 additions & 0 deletions test/__snapshots__/helpers.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,46 @@ exports[`Versioning should support multi env config in browserslist package.json
]
`;

exports[`Versioning should support object config in rule option 1`] = `
[
{
"parsedVersion": 18.14,
"target": "node",
"version": "18.14.0",
},
{
"parsedVersion": 70,
"target": "chrome",
"version": "70",
},
]
`;

exports[`Versioning should support object config with ignore option in rule option 1`] = `
[
{
"parsedVersion": 18.14,
"target": "node",
"version": "18.14.0",
},
]
`;

exports[`Versioning should support object config with query array in rule option 1`] = `
[
{
"parsedVersion": 18.14,
"target": "node",
"version": "18.14.0",
},
{
"parsedVersion": 70,
"target": "chrome",
"version": "70",
},
]
`;

exports[`Versioning should support resolving browserslist config in subdirectory 1`] = `
[
{
Expand Down
34 changes: 34 additions & 0 deletions test/helpers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,40 @@ describe("Versioning", () => {
expect(result).toMatchSnapshot();
});

it("should support object config in rule option", () => {
const config = determineTargetsFromConfig(
path.join(__dirname, ".browserslistrc"),
{
query: "node 18",
}
);
const result = parseBrowsersListVersion(config);
expect(result).toMatchSnapshot();
});

it("should support object config with query array in rule option", () => {
const config = determineTargetsFromConfig(
path.join(__dirname, ".browserslistrc"),
{
query: ["node 18"],
}
);
const result = parseBrowsersListVersion(config);
expect(result).toMatchSnapshot();
});

it("should support object config with ignore option in rule option", () => {
const config = determineTargetsFromConfig(
path.join(__dirname, ".browserslistrc"),
{
query: "node 18",
ignoreBrowserslistTargets: true,
}
);
const result = parseBrowsersListVersion(config);
expect(result).toMatchSnapshot();
});

it("should fail on incorrect browserslist target version", () => {
expect(() => {
determineTargetsFromConfig(".", "edge 100000");
Expand Down