npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

oxlint-plugin-vize

v0.435.0

Published

Oxlint JS plugin bridge for Vize Patina

Readme

oxlint-plugin-vize

Oxlint JS plugin bridge for Vize Patina.

This package lets Oxlint execute Patina through Vize's native binding while still using Oxlint's JS plugin model and rule configuration.

[!IMPORTANT] oxlint-plugin-vize is a terminal-first Vue SFC linting package. Until upstream Vue support in Oxlint matures, use oxlint-vize for original SFC locations in terminal and JSON output. Direct oxlint still has JS plugin location limits.

Main Features

  • Runs Vize Patina rules inside Oxlint as vize/* diagnostics, so Vue-specific findings can live beside Oxlint core rules in one command.
  • Keeps Oxlint's existing rules and built-in vue plugin active. The bridge adds Vize rules; it does not replace eqeqeq, no-console, or your existing vue/* setup.
  • Ships preset rule maps for JS/TS Oxlint configs: configs.recommended, configs.happyPath, configs.essential, configs.ecosystem, configs.opinionated, configs.nuxt, configs.all, and type-aware opt-in variants.
  • Ships createVizeLintConfig(), flatConfigs, and defineVizeLintConfig() for the Vite+ lint block in vite.config.ts, which is the only Oxlint configuration vp lint and vp check read.
  • Supports runtime settings through settings.vize, including locale, preset, and helpLevel.
  • Provides the oxlint-vize CLI wrapper, which runs Oxlint with a temporary location bridge for Vue and HTML files and reports their original paths and Patina locations.
  • Resolves Vize native bindings through platform-specific optional dependencies, so published installs do not need a separate @vizejs/native package.
  • Caches file contents and native rule results for the lifetime of the Oxlint process, reducing duplicate work when several Vize rules are enabled for the same file.

Performance

The bridge is optimized around Oxlint's per-rule execution model:

  • The first enabled Patina rule on a file runs native linting for that rule only.
  • If a second Patina rule is encountered on the same file, the bridge upgrades to one shared full-file Patina pass and reuses that result for the remaining Patina rules.
  • Exact source revisions and rule results are cached for up to 128 recently used file/settings pairs; edits replace revision-local diagnostics and reporting state.

Installation

oxlint-plugin-vize targets Node 22 and Node 24+ (^22 || >= 24). In this repository, Vite+ reads package.json#devEngines.runtime for you, so the usual setup is:

vp install
vp run --filter './npm/native' build
vp run --filter './npm/oxlint' build

Install vp once from the Vite+ install guide, then add it with:

vp install -D oxlint oxlint-plugin-vize

oxlint-plugin-vize pulls the appropriate Vize native binding for the current platform through optional dependencies, so no separate @vizejs/native install is required for published builds.

Usage

Which file you configure depends on which command you run.

| Command | Reads | | ----------------------- | ------------------------------------ | | vp lint, vp check | the lint block in vite.config.ts | | oxlint, oxlint-vize | .oxlintrc.json (or -c <path>) |

[!IMPORTANT] Vite+ never reads .oxlintrc.json. A .oxlintrc.json carrying jsPlugins and vize/* rules looks configured, but vp lint ignores the file, so Oxlint never sees a vize/* rule id and reports zero Vize diagnostics while exiting 0. vp lint --init does not migrate an existing .oxlintrc.json either: it writes a fresh lint block and leaves the old file in place. If you use vp lint, configure the lint block.

With vp lint (Vite+)

createVizeLintConfig() returns a complete lint block, so the jsPlugins entry cannot go missing. The default preset is "happy-path"/"general-recommended": use it when you want a safe Vue baseline without taking a position on stronger style or framework choices.

// vite.config.ts
import { defineConfig } from "vite-plus";
import { createVizeLintConfig } from "oxlint-plugin-vize";

export default defineConfig({
  lint: createVizeLintConfig({
    preset: "happy-path",
    rules: {
      "no-console": "warn",
    },
    settings: {
      helpLevel: "short",
    },
  }),
});

preset drives both the emitted rule map and settings.vize.preset when a single bundle is selected, so the two can never disagree. That matters because the bridge silently drops any vize/* rule outside the active preset: listing vize/ecosystem/router-link-require-to while the active preset is general-recommended reports nothing at all. createVizeLintConfig throws for that case, and for unknown vize/* ids, instead of leaving you with a config that looks enabled and reports nothing.

Use preset: "incremental" when you want only the rules you list, preset: "all" for every bundle at once, and preset: ["happy-path", "ecosystem"] or presets: ["happy-path", "ecosystem"] when you want several bundles without taking on all of them. Multiple-bundle configs emit settings.vize.preset: "incremental" so the runtime gate cannot suppress one selected bundle's rules while another bundle is active.

The emitted block always enables Oxlint's built-in vue plugin. Pass plugins to keep the rest of your project's plugin list; they are merged with vue, never replaced, because narrowing the list would silently drop everything those plugins report. A create-vue project keeps its generated set like this:

export default defineConfig({
  lint: {
    ...createVizeLintConfig({
      plugins: ["eslint", "typescript", "unicorn", "oxc"],
    }),
    ignorePatterns: ["dist/**"],
  },
});

For Flat Config-style composition in vite.config.ts, use spreadable fragments and collapse them back to Vite+'s object-shaped lint config:

import { defineConfig } from "vite-plus";
import { defineVizeLintConfig, flatConfigs } from "oxlint-plugin-vize";

export default defineConfig({
  lint: defineVizeLintConfig(...flatConfigs.recommended, ...flatConfigs.ecosystem, {
    ignorePatterns: ["dist/**"],
    rules: {
      "no-console": "warn",
    },
  }),
});

The exported fragments include flatConfigs.recommended, flatConfigs.happyPath, flatConfigs.essential, flatConfigs.ecosystem, flatConfigs.nuxt, flatConfigs.opinionated, and flatConfigs.all, plus the same *WithTypeAware variants as configs.

With oxlint or oxlint-vize

Enable Oxlint's built-in vue plugin as well as this JS plugin:

{
  "plugins": ["vue"],
  "jsPlugins": ["oxlint-plugin-vize"],
  "rules": {
    "eqeqeq": "error",
    "no-console": "warn",
    "vize/vue/require-v-for-key": "error",
    "vize/vue/no-v-html": "warn"
  }
}

This bridge only adds the vize/* rules. Oxlint's existing core rules and built-in plugin rules still run as configured, so checks like eqeqeq, no-console, or your existing vue/* setup continue to report normally.

If you want a lower-config JS/TS Oxlint setup, the package also exports preset rule maps:

import { configs } from "oxlint-plugin-vize";

export default {
  plugins: ["vue"],
  jsPlugins: ["oxlint-plugin-vize"],
  settings: {
    vize: {
      helpLevel: "short",
      preset: "opinionated",
      typeAware: true,
    },
  },
  rules: configs.opinionatedWithTypeAware,
};

configs.recommended, configs.happyPath, configs.essential, configs.ecosystem, configs.opinionated, configs.nuxt, and configs.all intentionally skip Vize's unstable type-aware rules for now. If you explicitly want those experimental rules too, use configs.recommendedWithTypeAware, configs.happyPathWithTypeAware, configs.ecosystemWithTypeAware, configs.opinionatedWithTypeAware, or createVizeRuleConfig({ includeTypeAware: true, preset: ... }). Set settings.vize.typeAware: true to run the shared full-file Patina pass with Corsa enabled; explicitly configured vize/type/* rules also opt in when they are queried one by one.

You can pass Patina settings through settings.vize:

{
  "settings": {
    "vize": {
      "locale": "ja",
      "preset": "essential",
      "helpLevel": "short",
      "typeAware": true
    }
  }
}
  • preset accepts "general-recommended"/"happy-path", "essential", "ecosystem", "incremental", "opinionated", "nuxt", or "all".
  • preset defaults to "general-recommended".
  • Bundle presets keep out-of-bundle rules quiet even if they are still listed in rules.
  • "incremental" skips bundle gating and runs only the Vize rules you explicitly configure in Oxlint.
  • "all" is accepted as a settings alias for "incremental"; use configs.all or createVizeLintConfig({ preset: "all" }) when you also want every rule emitted.
  • "ecosystem" enables Vize's Vue Router, Vue I18n, Pinia, Vue Test Utils, and Void Vue rules without taking on the full opinionated preset.
  • "opinionated" is the preset that enables Vize's built-in script rules such as vize/script/no-options-api.
  • Legacy aliases such as "GeneralRecommended", "Essential", "Ecosystem", "Incremental", "Opinionated", "Nuxt", and "happy-path" are still accepted for compatibility.
  • helpLevel accepts "full", "short", or "none". Short help keeps one actionable sentence and removes inline examples and trailing rationale.
  • helpLevel: "full" only expands the Patina remediation text. It does not restore original-SFC formatter anchors or machine-readable range fidelity.
  • typeAware: true enables Corsa-backed vize/type/* rules during shared Patina passes.
  • corsaPath selects a Corsa or TypeScript 7 native executable for type-aware linting. Omit it to use Vize's normal resolver.
  • showHelp is still accepted for backward compatibility, but helpLevel is the preferred setting.

For example, this keeps Oxlint focused on correctness-only Vize diagnostics while still allowing your existing Oxlint rules to run unchanged:

{
  "settings": {
    "vize": {
      "preset": "essential",
      "helpLevel": "short"
    }
  },
  "rules": {
    "vize/vue/require-v-for-key": "error",
    "vize/vue/require-scoped-style": "error"
  }
}

In that config, vize/vue/require-v-for-key can report, while vize/vue/require-scoped-style stays silent because it belongs to the broader "general-recommended" preset.

If you want to adopt Vize one rule at a time, use "preset": "incremental". In that mode, preset membership no longer suppresses configured rules, so only the Vize rules you list under rules will run.

For day-to-day terminal runs, the recommended command today is:

vp exec oxlint-vize -c .oxlintrc.json -f stylish src

oxlint-vize appends a temporary <script setup> location bridge for Vue and HTML files, including files with existing scripts. This lets Patina report the original SFC line and column through Oxlint's JS plugin pipeline. The wrapper rewrites temporary paths back to the original files; -f json retains those original positions for machine-readable diagnostics.

Limitations

  • Raw oxlint still misses files without <script> or <script setup>. It also anchors template diagnostics to an extracted script instead of the original template location. Use oxlint-vize when linting Vue and HTML files.
  • The wrapper's temporary files are not copied back when Oxlint fix flags are used; it warns when --fix or --fix-suggestions is passed.
  • With Oxlint 1.78 and an explicit complete JSON config containing ignorePatterns or overrides, the wrapper retains original file selection and ordered Vue overrides. This mode supports POSIX paths; inherited configs, import/type-aware project resolution, suppression state, ambiguous filenames, unsupported outside-root patterns and unknown option forms produce actionable errors.
  • Discovered, nested and dynamic configurations keep the existing wrapper path; the scoped JSON mode does not establish equivalent filtering for those configurations or other Oxlint versions.
  • Oxlint core rules that need JavaScript bindings extracted from Vue templates, such as template-aware unused-variable checks, still depend on upstream work in Oxc's Better Vue Support.
  • Direct oxlint original-SFC ranges depend on the JS plugin reporting work tracked in oxc-project/oxc#20465.
  • Type-aware Vize rules are experimental and excluded from the default exported configs. Opt into them explicitly with configs.recommendedWithTypeAware, configs.opinionatedWithTypeAware, or createVizeRuleConfig({ includeTypeAware: true, preset: ... }), and use settings.vize.typeAware: true when you want the shared full-file pass to run them eagerly.

Current expectations

  • This release is meant for terminal-first workflows.
  • The oxlint-vize wrapper reports original Patina positions in stylish and json; direct oxlint remains limited by its extracted-script JS plugin input.
  • Once Oxlint preserves original Vue positions for JS plugins, the temporary location bridge can be removed.