ESLint plugin that lints browser compatibility of API usage to help developers identify unsupported features in target browsers
npx @tessl/cli install tessl/npm-eslint-plugin-compat@6.0.0ESLint Plugin Compat is a TypeScript ESLint plugin that provides browser compatibility linting for web APIs and ES APIs. It helps developers identify when their code uses features that may not be supported in their target browsers by integrating with browserslist for flexible browser targeting configuration and leveraging compatibility data from MDN Browser Compat Data and Can I Use.
npm install eslint-plugin-compatimport compat from "eslint-plugin-compat";For CommonJS:
const compat = require("eslint-plugin-compat");import compat from "eslint-plugin-compat";
export default [compat.configs["flat/recommended"]];{
"plugins": ["compat"],
"extends": ["plugin:compat/recommended"],
"env": {
"browser": true
}
}{
"browserslist": ["defaults"]
}{
"settings": {
"polyfills": [
"Promise",
"WebAssembly.compile",
"fetch",
"Array.prototype.push"
]
}
}ESLint Plugin Compat is built around several key components:
compat rule that checks API usage against browser support dataMain plugin object that provides ESLint integration with browser compatibility checking functionality.
/**
* Main ESLint plugin export containing rules, configs, and metadata
*/
interface ESLintCompatPlugin {
/** Plugin metadata including name and version */
meta: {
name: string;
version: string;
};
/** Available rules provided by the plugin */
rules: {
compat: Rule.RuleModule;
};
/** Configuration presets for different ESLint config formats */
configs: {
"flat/recommended": Linter.FlatConfig;
recommended: Linter.Config;
};
/** @deprecated Use configs instead - will be removed in next major release */
config: {
"flat/recommended": Linter.FlatConfig;
recommended: Linter.Config;
};
}The core compat rule that performs browser compatibility checking of API usage.
/**
* ESLint rule that checks browser compatibility of API usage
*/
interface CompatRule extends Rule.RuleModule {
/** Rule metadata and configuration schema */
meta: {
docs: {
description: "Ensure cross-browser API compatibility";
category: "Compatibility";
url: string;
recommended: true;
};
type: "problem";
schema: [{ type: "string" }];
};
/** Rule factory function that creates the rule implementation */
create(context: Context): ESLintVisitorObject;
}
/**
* ESLint visitor object with AST node handlers for compatibility checking
*/
interface ESLintVisitorObject {
/** Handler for function call expressions */
CallExpression: (node: ESLintNode) => void;
/** Handler for constructor expressions */
NewExpression: (node: ESLintNode) => void;
/** Handler for member access expressions */
MemberExpression: (node: ESLintNode) => void;
/** Handler for expression statements */
ExpressionStatement: (node: ESLintNode) => void;
/** Handler for identifier nodes to track variable definitions */
Identifier: (node: ESLintNode) => void;
/** Handler executed when AST traversal completes */
"Program:exit": () => void;
}Rule context interface that extends ESLint's base context with plugin-specific settings.
/**
* Extended ESLint rule context with compat-specific settings
*/
interface Context extends Rule.RuleContext {
/** Plugin-specific configuration settings */
settings: {
/** Target browser strings (deprecated, use browserslist) */
targets?: string[];
/** Browser configuration (deprecated, use browserslist) */
browsers?: Array<string>;
/** Array of polyfilled API names to suppress warnings */
polyfills?: Array<string>;
/** Enable linting of ES APIs in addition to Web APIs */
lintAllEsApis?: boolean;
/** Browserslist configuration options */
browserslistOpts?: BrowsersListOpts;
};
}
/**
* Browserslist configuration options
*/
interface BrowsersListOpts {
/** Environment to use from browserslist config (production/development) */
env?: string;
/** Additional browserslist options */
[key: string]: any;
}Types for configuring browser targets and compatibility checking.
/**
* Browserslist configuration format
*/
type BrowserListConfig =
| string
| Array<string>
| {
production?: Array<string>;
development?: Array<string>;
}
| null;
/**
* Browser target specification
*/
interface Target {
/** Browser target identifier */
target: keyof TargetNameMappings;
/** Parsed version number for comparison */
parsedVersion: number;
/** Version string, number, or "all" for all versions */
version: number | string | "all";
}
/**
* Mappings from browser target IDs to display names
*/
interface TargetNameMappings {
chrome: "Chrome";
firefox: "Firefox";
safari: "Safari";
ios_saf: "iOS Safari";
ie: "IE";
ie_mob: "IE Mobile";
edge: "Edge";
baidu: "Baidu";
electron: "Electron";
blackberry_browser: "Blackberry Browser";
edge_mobile: "Edge Mobile";
and_uc: "Android UC Browser";
and_chrome: "Android Chrome";
and_firefox: "Android Firefox";
and_webview: "Android Webview";
and_samsung: "Samsung Browser";
and_opera: "Opera Android";
opera: "Opera";
opera_mini: "Opera Mini";
opera_mobile: "Opera Mobile";
node: "Node.js";
kaios: "KaiOS";
}Types for ESLint AST nodes that the plugin processes during compatibility checking.
/**
* ESLint AST node representation
*/
interface ESLintNode {
/** Node name/identifier */
name: string;
/** AST node type */
type: string;
/** Node value if applicable */
value?: unknown;
/** Object reference for member expressions */
object?: ESLintNode;
/** Parent node reference */
parent?: ESLintNode;
/** Expression node reference */
expression?: ESLintNode;
/** Property node for member expressions */
property?: ESLintNode;
/** Callee node for call expressions */
callee?: ESLintNode & {
name: string;
type?: string;
};
}
/**
* Supported AST node types for compatibility checking
*/
enum AstNodeTypes {
MemberExpression = "MemberExpression",
CallExpression = "CallExpression",
NewExpression = "NewExpression"
}Types for compatibility data used by the plugin's data providers.
/**
* API compatibility metadata with target resolution
*/
interface AstMetadataApiWithTargetsResolver {
/** Unique API identifier */
id: string;
/** Can I Use database identifier */
caniuseId?: string;
/** API kind (web/es) */
kind?: "web" | "es";
/** API type (function/property/constructor) */
type?: string;
/** API name */
name?: string;
/** Object that contains this API */
object: string;
/** AST node type this API appears in */
astNodeType: "MemberExpression" | "CallExpression" | "NewExpression";
/** Property name for member expressions */
property?: string;
/** Prototype chain identifier */
protoChainId: string;
/** Full prototype chain */
protoChain: Array<string>;
/** Function to determine which targets don't support this API */
getUnsupportedTargets: (
node: AstMetadataApiWithTargetsResolver,
targets: Target[]
) => Array<string>;
}
/**
* Callback function for handling compatibility rule failures
*/
type HandleFailingRule = (
node: AstMetadataApiWithTargetsResolver,
eslintNode: ESLintNode
) => void;// eslint.config.mjs
import compat from "eslint-plugin-compat";
export default [compat.configs["flat/recommended"]];// package.json
{
"browserslist": ["defaults"]
}{
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}{
"browserslist": {
"production": [
"> 1%",
"not dead"
],
"modern": [
"last 1 chrome version",
"last 1 firefox version"
]
}
}{
"settings": {
"browserslistOpts": {
"env": "modern"
}
}
}{
"settings": {
"polyfills": [
"Promise",
"WebAssembly.compile",
"fetch",
"Array.prototype.push"
],
"lintAllEsApis": true,
"browserslistOpts": {
"env": "production"
}
}
}{
"plugins": ["compat"],
"extends": ["plugin:compat/recommended"],
"env": {
"browser": true
},
"settings": {
"polyfills": ["fetch", "Promise"]
}
}