Lint JavaScript/TypeScript source with oxlint's built-in rules and optional custom Elixir rules.
Combines native Rust performance for 650+ standard rules with
the ability to write project-specific rules in Elixir using
the same AST that OXC.parse/2 returns.
Examples
{:ok, diags} = OXC.Lint.run("debugger;", "test.js",
rules: %{"no-debugger" => :deny})
{:ok, []} = OXC.Lint.run("export const x = 1;\n", "test.ts")
Summary
Types
An oxlint plugin name, such as "react" or "jsx-a11y".
Rule severity in lint options. Findings report :error for :deny and :warning for :warn.
Types
@type diagnostic() :: OXC.Diagnostic.t()
@type global_access() :: :readonly | :writable | :off
@type plugin() :: String.t()
An oxlint plugin name, such as "react" or "jsx-a11y".
@type severity() :: :allow | :warn | :deny
Rule severity in lint options. Findings report :error for :deny and :warning for :warn.
Functions
@spec run([String.t()], [OXC.Lint.TypeAware.option()]) :: {:ok, [diagnostic()]} | {:error, [diagnostic()]}
Lint source code with oxlint's built-in rules and optional custom rules.
Pass a list of files with type_aware: true to run TypeScript type-aware
rules through tsgolint headless mode:
OXC.Lint.run(["lib/app.ts"],
type_aware: true,
tsgolint: "tsgolint",
rules: %{"typescript/no-floating-promises" => :deny})Categories select type-aware rules too, from the enabled :plugins, so
rules: %{"correctness" => :deny} runs typescript/no-floating-promises.
Options
:rules— map of rule names to severity (:deny,:warn,:allow). Rule names follow oxlint conventions:"eqeqeq","react/no-danger","typescript/no-explicit-any", etc. Categories such as"correctness"and"all"select every rule in them."all"applies first, then categories, then single rules, so a single rule overrides its category.:plugins— oxlint plugin names to enable, such as["react", "jsx-a11y"], accepting the same names and aliases as an oxlint config file. Default: oxlint's default plugins. Unknown names are errors.:fix— compute fix suggestions. Default:false:env— list of enabled Oxlint environment names, for example["browser", "node", "mocha"].:globals— map of global names to:readonly,:writable, or:off, for example%{"jQuery" => :readonly}.:custom_rules— list of{module, severity}tuples for Elixir rules. Each module must implement theOXC.Lint.Rulebehaviour.:settings— arbitrary map passed to custom rule context.
Examples
# Built-in rules only
{:ok, diags} = OXC.Lint.run("debugger;", "test.js",
rules: %{"no-debugger" => :deny})
# With specific plugins and rules
{:ok, diags} = OXC.Lint.run(source, "app.tsx",
plugins: ["react", "typescript"],
rules: %{"no-console" => :warn, "react/no-danger" => :deny}
)
# With custom Elixir rules
{:ok, diags} = OXC.Lint.run(source, "app.ts",
custom_rules: [{MyApp.NoConsoleLog, :warn}]
)
@spec run(iodata(), String.t(), [option()]) :: {:ok, [diagnostic()]} | {:error, [diagnostic()]}
@spec run!(iodata(), String.t(), [option()]) :: [diagnostic()]
Like run/3 but raises on errors.
@spec type_aware_rules(keyword()) :: {:ok, %{required(String.t()) => severity() | {severity(), term()}}} | {:error, [diagnostic()]}
Resolve the type-aware rules that run/2 submits to tsgolint for these options.
all and category filters in :rules select type-aware rules from the enabled
:plugins through oxlint's rule registry. Rules named typescript/* keep their
options and override their categories. Other rules are syntax rules and are left out.
{:ok, %{"typescript/no-floating-promises" => :deny}} =
OXC.Lint.type_aware_rules(rules: %{"typescript/no-floating-promises" => :deny})