eslint-plugin-lit
An ESLint plugin with 25 rules that catch Lit-specific template, attribute, and lifecycle mistakes at lint time.
Repository Health
Technical Analysis
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
recommendedshareable config plus anallconfig, in both legacy.eslintrcand flat-config formats - A template analyzer that parses tagged
htmlliterals into a real DOM tree viaparse5for accurate HTML validation - Per-project
settings.lit.elementBaseClassessupport for recognizing custom classes that extendLitElement - 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/updatedwithout callingsuper() - Migrating a codebase off legacy Lit template syntax (
lit-htmlv1-style bindings) toward current syntax - Pairing with
eslint-plugin-wcto 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.
Used by 3 apps in this directory
AFFiNE
Productivity · Project Management · Note Taking
Write, draw, and plan in one infinite canvas — the open-source alternative to Notion and Miro that keeps your data yours.
authentik
Authentication · Security
The self-hosted Identity Provider that replaces Okta, Auth0, and Entra ID with a unified SSO platform supporting SAML, OAuth2/OIDC, LDAP, RADIUS, and WebAuthn.
Umbraco CMS
CMS
The friendly open-source .NET CMS that gives developers full control over content, structure, and delivery without lock-in.