eslint-plugin-lit

An ESLint plugin with 25 rules that catch Lit-specific template, attribute, and lifecycle mistakes at lint time.

Tool
npm
v2.3.1
138stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
67/100Good
Development Activity72
Maintenance48
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
80/100Excellent
Architecture84
Code Quality88
Innovation72
Learning Curve75

eslint-plugin-lit is a focused ESLint plugin for teams building with Lit and lit-html. Rather than relying on generic JavaScript linting, it parses tagged template literals as HTML (via parse5) and cross-references them against a component’s LitElement class definition, so it can flag mistakes that are invisible to a standard linter: mismatched attribute casing, invalid HTML inside a template, duplicate bindings, calling this.requestUpdate() in the wrong place, or forgetting to call super() in a lifecycle method.

The plugin ships 25 rules covering naming conventions, template correctness, legacy-syntax migration, and Lit lifecycle pitfalls, along with recommended and all presets for both the legacy .eslintrc format and ESLint’s flat config. It also exposes a lit.elementBaseClasses setting so projects with a custom base class extending LitElement are still recognized correctly. Maintained by James Garbutt (also the author of eslint-plugin-wc), it has been actively developed since 2018 and is a common companion dependency wherever Lit or web-component-based UI is in use.

What You Get

  • 25 rules covering attribute naming, template correctness, lifecycle safety, and legacy-syntax migration
  • A recommended shareable config plus an all config, in both legacy .eslintrc and flat-config formats
  • A template analyzer that parses tagged html literals into a real DOM tree via parse5 for accurate HTML validation
  • Per-project settings.lit.elementBaseClasses support for recognizing custom classes that extend LitElement
  • Individually documented rules (with fix suggestions) under docs/rules/, so teams can opt into only the checks they want
  • Full TypeScript typings for every rule, published as part of the package

Common Use Cases

  • Enforcing consistent, case-correct attribute names across a design-system’s Lit components
  • Catching invalid or malformed HTML inside html\…“ templates before it reaches the browser
  • Preventing common Lit lifecycle bugs, such as overriding connectedCallback/updated without calling super()
  • Migrating a codebase off legacy Lit template syntax (lit-html v1-style bindings) toward current syntax
  • Pairing with eslint-plugin-wc to get combined web-component and Lit-specific linting in one ESLint config

Under The Hood

Architecture The plugin follows the standard ESLint plugin shape (src/index.ts exports a rules map and configs object consumed by ESLint’s plugin loader) but layers a genuine static-analysis engine on top: src/template-analyzer.ts implements a TemplateAnalyzer that takes a tagged-template TaggedTemplateExpression AST node, reconstructs its HTML string (substituting expression placeholders via templateExpressionToHtml), and parses it with parse5 (using the parse5-htmlparser2-tree-adapter) into a real DOM-like tree that rules can walk with enterElement/enterTextNode/enterCommentNode visitor callbacks; a WeakMap-backed cache keyed on the AST node avoids re-parsing the same template across rules in a single lint pass. src/util.ts supplies the shared primitives every rule depends on — isLitClass, getPropertyMap (extracting a component’s reactive-property map from @property/static properties), and casing helpers — which keeps the 25 individual rule files in src/rules/ thin and declarative, each exporting a single Rule.RuleModule with its own meta/schema/create. Nothing here would break if the core template-analysis abstraction changed, since each rule only touches it through the visitor interface, not the parser internals directly.

Tech Stack Written in TypeScript (99%+ of the codebase) with parse5 and parse5-htmlparser2-tree-adapter as the only runtime dependencies, and ESLint itself declared as a peer dependency (>= 8) so the plugin resolves against whatever ESLint version the consuming project uses. The dev toolchain is fully modern: typescript-eslint and @eslint/js for self-linting under ESLint’s own flat config, prettier for formatting, tsc for the build, c8 for coverage, and mocha/chai for the test runner. Node’s package manifest requires >= 18, and CI runs the matrix against Node 20, 22, and 25.

Code Quality Every one of the 25 rules under src/rules/ has a matching test file under src/test/rules/, plus dedicated suites for template-analyzer_test.ts, util_test.ts, and configs_test.ts — there is no rule without direct test coverage. The codebase is fully typed, using ESLint’s own Rule.RuleModule and estree/ESTree types rather than loosely-typed any, and augments them with explicit interfaces (BabelDecorator, BabelAccessorProperty) to model decorator and accessor-property syntax that isn’t yet in stable ESTree. GitHub Actions CI runs lint, build, and test across three Node versions on every push and PR, with Coveralls reporting coverage; prepublishOnly re-runs lint and test before any npm release, preventing an untested build from shipping.

What Makes It Unique Unlike lint plugins that pattern-match on raw template strings, eslint-plugin-lit actually parses html\…`tagged templates into a structured DOM tree and cross-references it against the enclosing class's reactive-property declarations — meaning rules like attribute-naming or duplicate-binding detection are working with real HTML structure and real property metadata rather than regexes. That combination (AST-level class analysis + genuine HTML parsing of template literals, cached per lint pass) is what lets it catch a category of Lit-specific bugs — casing mismatches, invalid nested HTML,super()` omissions — that generic ESLint/TypeScript tooling has no way to see.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search