eslint-plugin-no-comment-slop
v0.3.0
Published
Flags AI comment slop in JavaScript and TypeScript. Runs in ESLint, oxlint and rslint
Maintainers
Readme
eslint-plugin-no-comment-slop
Flags AI comment slop in JavaScript and TypeScript. The same module runs unchanged in ESLint, oxlint and rslint because it only uses the rule APIs all three linters implement. CI runs one fixture through eslint 9, eslint 10, oxlint and rslint and requires identical diagnostics.
Before:
// ============================================
// Utilize this robust helper to seamlessly retrieve the user — it is
// crucial to note that it delves into the cache first.
export const getUser = (id) => cache.get(id) ?? fetchUser(id); // fetches the userAfter:
/**
* Cache first, network second
*/
export const getUser = (id) => cache.get(id) ?? fetchUser(id);Install
npm install --save-dev eslint-plugin-no-comment-slopNeeds Node 24+ and one of: ESLint 9+ with flat config, oxlint with jsPlugins, or rslint.
Usage
ESLint (eslint.config.mjs):
import noCommentSlop from "eslint-plugin-no-comment-slop";
export default [noCommentSlop.configs.recommended];To adjust a rule, override it after the preset:
export default [
noCommentSlop.configs.recommended,
{
rules: {
"no-comment-slop/no-trailing-period": "off",
"no-comment-slop/no-jargon": ["error", { extraWords: ["synergy"] }],
},
},
];Consider leaving tests alone. Generated tests often earn their comments: a line or two per unit or e2e case documents intent that would otherwise live nowhere. Whether to lint test comments is the maintainer's call; to skip them:
export default [
{
...noCommentSlop.configs.recommended,
ignores: ["**/*.test.*", "**/*.spec.*", "**/tests/**", "**/e2e/**"],
},
];oxlint (.oxlintrc.json) has no preset support for JS plugins, so enable each rule from the table below:
{
"jsPlugins": ["eslint-plugin-no-comment-slop"],
"rules": {
"no-comment-slop/no-jargon": "error",
"no-comment-slop/no-em-dash": "error"
}
}rslint (rslint.config.mjs):
import noCommentSlop from "eslint-plugin-no-comment-slop";
export default [
{
files: ["**/*.{js,ts}"],
...noCommentSlop.configs.recommended,
},
];Rules
Every rule is part of the recommended config. The 🔧 fixes are mechanical: delete a banner, drop a period, turn // into JSDoc. --fix never rewrites your wording; no-jargon and no-em-dash report with guidance instead.
🔧 Automatically fixable by the --fix CLI option.
💡 Manually fixable by editor suggestions.
| Name | Description | 🔧 | 💡 | | :----------------------------------------------------------------- | :------------------------------------------------------------------ | :- | :- | | max-comment-lines | Limit how many lines a comment may span | | | | multiline-jsdoc-format | Require /** and / on their own lines in a multi-line JSDoc comment | 🔧 | | | no-banner-comment | Disallow ASCII separator and banner comments | 🔧 | | | no-em-dash | Disallow em dashes (and optionally en dashes) in comments | | | | no-foreign-syntax | Disallow comment syntax imported from other languages | | | | no-jargon | Disallow inflated vocabulary in comments | | 💡 | | no-trailing-comment | Disallow comments on the same line as code | | | | no-trailing-period | Disallow a trailing period at the end of a comment | 🔧 | | | prefer-jsdoc-for-exports | Require /* / rather than // for the comment documenting an export | 🔧 | | | prefer-jsdoc-for-members | Require /* */ rather than // for the comment documenting a member | 🔧 | | | require-member-docs | Require docs on every member once most of a type is documented | | |
What it catches
One flagged example per rule. Each rule doc has the matching fix.
max-comment-lines — a wall of prose above one call:
// This helper computes the value by first checking the cache,
// then falling back to the network, then retrying twice with
// exponential backoff, and finally giving up and returning null
// so the caller can decide what to do next.
const value = load();multiline-jsdoc-format — text hanging off the /** line:
/** Stamped into every artifact so files are self-describing.
* Bump only on a breaking change */
export const schemaVersion = 3;no-banner-comment — ASCII rulers and banners:
// ============================
// --- helpers ---
/* ************************** */no-em-dash — the em dash aside:
// caches the value — see the loaderno-foreign-syntax — Rust and C# doc habits in JavaScript:
/// Returns the user id
// <summary>Gets the id</summary>
//#region helpersno-jargon — inflated vocabulary:
// utilize the robust cache to streamline lookupsno-trailing-comment — a comment restating the line it sits on:
const retries = 3; // number of retriesno-trailing-period — a sentence-ending period on a one-line comment:
// waits for the lock before writing.prefer-jsdoc-for-exports — // above an export, which no editor shows on hover:
// Parses the config file
export function parseConfig(path) {}prefer-jsdoc-for-members — the same for a member:
interface RecordOptions {
// run without a window
headless: boolean;
}require-member-docs — one member left out once the rest are documented:
interface RecordOptions {
/** module to load */
module: string;
/** entry function name */
fn: string;
/** browser binary */
browser: string;
url: string;
}