Writing JS Plugins
INFO
JS plugins are currently in alpha, and remain under active development.
All APIs should behave identically to ESLint. If you find any differences in behavior, that's a bug - please report it.
ESLint-compatible API
Oxlint provides a plugin API identical to ESLint's. See ESLint's docs on creating a plugin and custom rules.
A simple plugin which flags files containing more than 5 class declarations:
js
// plugin.js
const rule = {
create(context) {
let classCount = 0;
return {
ClassDeclaration(node) {
classCount++;
if (classCount === 6) {
context.report({ message: "Too many classes", node });
}
},
};
},
};
const plugin = {
meta: {
name: "best-plugin-ever",
},
rules: {
"max-classes": rule,
},
};
export default plugin;
``````json [.oxlintrc.json]
{
"jsPlugins": ["./plugin.js"],
"rules": {
"best-plugin-ever/max-classes": "error"
}
}
``````ts [oxlint.config.ts]
import { defineConfig } from "oxlint";
export default defineConfig({
jsPlugins: ["./plugin.js"],
rules: {
"best-plugin-ever/max-classes": "error",
},
});
``````js
import { eslintCompatPlugin } from "@oxlint/plugins";
const rule = {
createOnce(context) {
// Define counter variable
let classCount;
return {
before() {
// Reset counter before traversing AST of each file
classCount = 0;
},
// Same as before
ClassDeclaration(node) {
classCount++;
if (classCount === 6) {
context.report({ message: "Too many classes", node });
}
},
};
},
};
const plugin = eslintCompatPlugin({
meta: {
name: "best-plugin-ever",
},
rules: {
"max-classes": rule,
},
});
export default plugin;
``````diff
- const plugin = {
+ const plugin = eslintCompatPlugin({
``````diff
- create(context) {
+ createOnce(context) {
``````diff
- let classCount = 0;
+ let classCount;
return {
+ before() {
+ classCount = 0; // Reset counter
+ },
ClassDeclaration(node) {
classCount++;
if (classCount === 6) {
context.report({ message: "Too many classes", node });
}
},
};
``````js
// This rule does not run on files which start with a `// @skip-me` comment
const rule = {
createOnce(context) {
return {
before() {
if (context.sourceCode.text.startsWith("// @skip-me")) {
return false;
}
},
FunctionDeclaration(node) {
// Do stuff
},
};
},
};
``````js
const rule = {
create(context) {
if (context.sourceCode.text.startsWith("// @skip-me")) {
return {};
}
return {
FunctionDeclaration(node) {
// Do stuff
},
};
},
};
``````js
const rule = {
createOnce(context) {
return {
Program(node) {
// This always runs for every file, even if it
// doesn't contain any `FunctionDeclaration`s
},
FunctionDeclaration(node) {
/* do stuff */
},
};
},
};
``````js
const rule = {
create(context) {
let classCount = 0;
return {
ClassDeclaration(node) {
classCount++;
if (classCount === 6) {
context.report({ message: "Too many classes", node });
}
},
};
},
};