Skip to content

Repository files navigation

eslint-plugin-consistent-comments

License: MIT npm version

Enforce consistent comment styles: single-line (//) for code, multi-line (/* */) for documentation

An ESLint plugin that automatically detects and enforces the appropriate comment style based on content. Commented-out code uses //, while documentation and explanatory text use /* */.

πŸ€” Why?

I want to have a clear distinction between commented-out code and documentation.

Commented-out code should probably be removed from production code, while documentation should stay.

✨ Features

  • πŸ€– Smart Detection - Automatically identifies code vs. documentation in comments using AST parsing
  • πŸ”§ Auto-fix - Converts comments to the correct style with eslint --fix
  • πŸ“ Smart Merging - Consecutive single-line text comments are merged into multi-line block format
  • πŸ›‘οΈ Safe Conversion - Avoids breaking comments that contain */ in their text
  • πŸ“¦ ESLint 9.x - Compatible with modern flat config format
  • 🎯 TypeScript & JavaScript - Works with both languages
  • ⚑ Zero Config - Works out of the box with sensible defaults

πŸ“₯ Installation

npm install eslint-plugin-consistent-comments --save-dev

Or using your preferred package manager:

pnpm add -D eslint-plugin-consistent-comments
# or
yarn add -D eslint-plugin-consistent-comments

πŸš€ Quick Start

Add to your eslint.config.js:

import commentsPlugin from 'eslint-plugin-consistent-comments';

export default [
  {
    plugins: {
      comments: commentsPlugin,
    },
    rules: {
      'comments/comment-style': 'error',
    },
  },
];

Then run ESLint with auto-fix:

npx eslint . --fix

πŸ“– Usage

The Problem

Inconsistent comment styles make code harder to read:

/* const oldCode = 'should be single-line'; */ // ❌ Code in multi-line
// This explains the function below              // ❌ Text in single-line

The Solution

This plugin enforces:

// const oldCode = 'should be single-line';    // βœ… Code in single-line
/* This explains the function below */ // βœ… Text in multi-line

Consecutive Comment Merging

When multiple single-line text comments appear consecutively (without empty lines), they're automatically merged into a multi-line block comment:

Before:

// This is a documentation comment
// that spans multiple lines
// for better readability

After:

/*
 * This is a documentation comment
 * that spans multiple lines
 * for better readability
 */

What Gets Detected as Code?

The plugin uses AST (Abstract Syntax Tree) parsing to accurately detect code, not just regex patterns. It recognizes:

  • Declarations: const, let, var, function, class, interface, type, enum
  • Control Flow: if, else, for, while, switch, return, throw
  • Functions: function foo(), () => {}, arrow functions
  • Imports/Exports: import, export
  • Method Calls: obj.method(), foo()
  • Operators: Assignments, comparisons
  • Data Structures: Arrays [...], objects {...}
  • Type Annotations: : string, : number
  • JSX: <Component />
  • Expressions: true, 42, "string", object/array literals

Special Cases & Safety

The plugin intelligently handles edge cases:

Comments containing */

Comments that contain */ in their text are not converted to multi-line format to avoid breaking syntax:

// These should NOT be converted to /* */ (results in invalid code)
// βœ… Stays as single-line comment to prevent syntax errors

Triple-slash directives

TypeScript directives and special comment forms are preserved:

/// <reference types="node" />           // βœ… Not converted
// @ts-ignore: special case              // βœ… Not converted
// eslint-disable-next-line no-unused-vars // βœ… Not converted

πŸ“‹ Examples

Before Auto-fix

/* const x = 5; */
/* function test() { return true; } */
// This is a documentation comment
// that spans multiple lines

/*
  const multiple = 'lines';
  const of = 'code';
*/

After Auto-fix

// const x = 5;
// function test() { return true; }
/*
 * This is a documentation comment
 * that spans multiple lines
 */

// const multiple = 'lines';
// const of = 'code';

βš™οΈ Configuration

Use Recommended Config

import commentsPlugin from 'eslint-plugin-consistent-comments';

export default [
  {
    plugins: {
      comments: commentsPlugin,
    },
    rules: {
      ...commentsPlugin.configs.recommended.rules,
    },
  },
];

With Other Plugins

import commentsPlugin from 'eslint-plugin-consistent-comments';
import tseslint from 'typescript-eslint';

export default [
  ...tseslint.configs.recommended,
  {
    plugins: {
      comments: commentsPlugin,
    },
    rules: {
      'comments/comment-style': 'error',
    },
  },
];

Rule Options

Currently, the rule has no options and works with sensible defaults. Future versions may add configuration options.

πŸ§ͺ Testing

Clone this repository, install dependencies, and run tests:

# Install dependencies
pnpm install

# Run tests
pnpm test

# Run tests with coverage
pnpm run coverage

# Build the plugin
pnpm build

Try the demo:

# Check for violations
node demo.mjs

# Auto-fix violations
node demo.mjs --fix

πŸ—οΈ Development

Project Structure

src/
  index.ts              # Main plugin implementation
tests/
  index.test.ts         # Test suite
  fixtures/             # Test fixtures
examples/
  before-fix.ts         # Example with violations
  after-fix.ts          # Example after fixes
  integration-example.ts # Comprehensive examples

Package Scripts

  • pnpm build β€” Build with unbuild (outputs CJS/ESM and type declarations)
  • pnpm test β€” Run tests with Vitest
  • pnpm test:watch β€” Run tests in watch mode
  • pnpm coverage β€” Generate coverage reports
  • pnpm lint β€” Run ESLint and auto-fix issues
  • pnpm typecheck β€” Run TypeScript type checks

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“ License

MIT Β© Johan Meester

πŸ”— Related Projects

🎯 How It Works

The plugin uses a sophisticated approach to distinguish between code and text:

  1. AST Parsing: Uses espree (ESLint's parser) to attempt parsing comment content as JavaScript/TypeScript
  2. Multiple Parse Attempts: Tries parsing as:
    • Complete program (statements)
    • Expression (wrapped in parentheses)
    • Statement (wrapped in a function body)
  3. Accurate Detection: If the content parses successfully, it's code; otherwise, it's text
  4. Consecutive Grouping: Merges consecutive single-line text comments into multi-line blocks
  5. Safety First: Skips conversion when it would create invalid syntax

This approach is far more reliable than regex patterns and handles edge cases like:

  • /* true */ β†’ // true (valid code, single boolean value)
  • /* This is true */ β†’ stays as /* This is true */ (text, not code)

πŸ’‘ Inspiration

This plugin was created to enforce a consistent commenting style that makes it easier to:

  • Distinguish between commented-out code (temporary, should be reviewed/removed)
  • Documentation comments (permanent, explains intent)
  • Keep documentation organized in proper multi-line block format

πŸ“š Further Reading

For more detailed documentation, see:


Made with ❀️ for better code consistency

About

An eslint plugin to format comments in a consistent way.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages