vue-eslint-parser
The ESLint custom parser that lets you lint the <template> section of Vue single-file components.
Repository Health
Technical Analysis
vue-eslint-parser is the official ESLint custom parser for .vue single-file components, maintained under the vuejs GitHub organization. Where ESLint’s default parser (Espree) only understands JavaScript, vue-eslint-parser splits a .vue file into its <template>, <script>, and <style> blocks, parses the template into a Vue-specific AST, and delegates script parsing to a configurable underlying parser such as @typescript-eslint/parser or @babel/eslint-parser. This is the parser that makes eslint-plugin-vue’s template-aware rules possible.
Beyond basic parsing, it exposes parserServices methods like defineTemplateBodyVisitor and defineDocumentVisitor so custom ESLint rules can traverse Vue templates with the same visitor pattern rule authors already use for JavaScript AST nodes. It supports both Vue 2 and Vue 3 template semantics (togglable via vueFeatures options such as filter and interpolationAsNonHTML), handles <script setup> scope analysis, and parses v-bind() CSS variable injection inside <style> blocks.
What You Get
- Template AST parsing - Converts the
<template>block of a.vuefile into aVElement/VDocumentFragmentAST that ESLint rules can traverse alongside the script AST. - Pluggable script parser - Delegates
<script>and<script setup>parsing to any configured parser (@typescript-eslint/parser,@babel/eslint-parser, or a per-language map) so TypeScript and JSX inside Vue components lint correctly. - Vue 2/Vue 3 feature toggles -
vueFeaturesoptions likefilter,interpolationAsNonHTML, andstyleCSSVariableInjectioncontrol which version’s template semantics get parsed. - Parser services for rule authors -
defineTemplateBodyVisitor,defineDocumentVisitor, anddefineCustomBlocksVisitorgive custom ESLint rules a visitor-pattern API for templates, the document fragment, and custom SFC blocks. <script setup>scope analysis - Resolves variables declared in<script setup>against their usage in the template so rules can flag unused or undefined references accurately.
Common Use Cases
- Building eslint-plugin-vue rules - Rule authors use the parser’s
parserServicesto write lint rules that inspect Vue template bindings and directives with the same ergonomics as JavaScript AST rules. - Linting Vue SFCs in CI - Teams set
vue-eslint-parseras their ESLint parser for*.vuefiles so<template>mistakes (bad directive expressions, typos in interpolations) are caught in CI rather than at runtime. - Custom template tokenizers for alternative template languages - Plugins like eslint-plugin-vue-pug use the parser’s
templateTokenizeroption to support non-HTML template languages such as Pug. - Migrating between Vue 2 and Vue 3 codebases - The
vueFeatures.filterandinterpolationAsNonHTMLtoggles let teams lint against the correct template parsing semantics during a Vue 2-to-3 migration.
Under The Hood
Architecture
The parseForESLint entry point in src/index.ts orchestrates a layered pipeline: it decides whether the input is a .vue SFC or a plain script (isVueFile), then for SFCs runs HTMLTokenizer/HTMLParser (src/html) to build a VDocumentFragment, computes a LocationCalculatorForHtml to map offsets between the outer HTML source and extracted inner blocks, resolves the configured script parser via getScriptParser/getParserLangFromSFC (src/common/parser-options.ts), delegates to parseScript/parseScriptElement/parseScriptSetupElements (src/script, src/script-setup), runs parseStyleElements (src/style) for v-bind() CSS injection, and finally merges everything with analyzeScope/analyzeScriptSetupScope for eslint-scope integration. parser-services.ts then attaches parserServices (wrapping a vendored NodeEventGenerator/TokenStore under src/external/) so rule authors get visitor-pattern traversal. The core contract every downstream consumer (eslint-plugin-vue, community parsers) depends on is this merged AST shape plus the parserServices API — changing either is a breaking change for the whole ecosystem.
Tech Stack
Written entirely in TypeScript, compiled with tsdown to a CJS/ESM-compatible dist per the package’s exports map. Runtime dependencies are narrow and precisely version-ranged: debug for diagnostics, eslint-scope/eslint-visitor-keys pinned to match ESLint’s own major lines, espree (ESLint’s default parser, used as the underlying tokenizer), esquery for selector-based traversal, and semver for version gating. A peer dependency on eslint ^8.57 || ^9 || ^10 covers three major ESLint lines simultaneously. Dev tooling includes vitest/@vitest/coverage-v8 for testing and its own flat eslint.config.mjs with typescript-eslint, Prettier, and eslint-plugin-unicorn. CI runs a GitHub Actions matrix across Node 18/20/21/lts on Ubuntu, Windows, and macOS against ESLint 9 and 10, plus a weekly cron.
Code Quality
The test suite pairs 11 top-level *.test.ts files (AST shape, tokens, variable references, custom block/document visitors, CRLF handling, integration tests) with an extensive golden-file strategy: 300+ fixture directories under test/fixtures/ast, each a source.vue with regenerable expected-AST snapshots (npm run update-fixtures) — a testing approach well matched to a parser, since it catches AST regressions unit tests alone would miss. The codebase is fully typed TypeScript with exported ParserOptions/AST types, parse errors are collected as typed entries on the AST rather than thrown or swallowed, and the project lints itself via ESLint + Prettier in CI with Codecov coverage reporting. No test-coverage or typing gaps were found.
API Design
The public surface is deliberately small: parseForESLint/parse satisfy ESLint’s parser contract, and a meta export satisfies ESLint 9’s parser-metadata requirement. Configuration is purely additive on top of standard parserOptions (parser, vueFeatures, templateTokenizer), so an existing Espree-based config migrates with a one-line change. parserServices methods mirror ESLint’s own rule-authoring conventions (defineTemplateBodyVisitor returns the same shape as a rule’s create()), keeping the learning curve low for anyone who already writes ESLint rules. Advanced features like custom template tokenizers and custom block parsers are explicitly flagged in the README as experimental/plugin-developer-only — an honest signal about API stability rather than over-promising. This is not novel technology so much as a narrowly-scoped, well-executed adapter over ESLint’s parser contract, with excellent ergonomics for that niche.
Used by 8 apps in this directory
1Panel
Devops · Hosting Control Panel · Monitoring
The only open-source VPS control panel with native AI agent runtime — deploy websites, Docker stacks, and local LLMs from one web interface.
BillionMail
Marketing
Self-hosted email server and marketing platform that gives you unlimited sending, full deliverability control, and AI-assisted campaigns without monthly fees.
CodeSandbox
Code Editors · Developer Tools
Instantly ready browser-based IDE that runs full npm dependency resolution and transpilation entirely client-side, with no server needed.
Flowfile
Data Engineering
Visual ETL that compiles to Polars — build pipelines on a canvas, export as standalone Python, and run anywhere without platform lock-in.
Frappe CRM
CRM
Open-source CRM with unlimited users, built-in Twilio, Exotel, WhatsApp, and ERPNext integrations — self-host in minutes.
listmonk
Marketing · Blogging
High-performance, self-hosted newsletter and mailing list manager packaged as a single binary with built-in analytics, transactional messaging, and multi-channel delivery.
OnetimeSecret
Security
Generate self-destructing single-use links to share passwords and sensitive data without leaving traces in inboxes or chat logs.
Scalar
Developer Tools
Beautiful, interactive OpenAPI documentation with a built-in offline-first API client and multi-language code generation — all in one open-source platform.