{"id":26567,"library":"unified-lint-rule","title":"unified-lint-rule","description":"A helper package for the unified ecosystem that simplifies creating linting rules for processors like remark, retext, and rehype. Version 3.0.1 is the current stable release (ESM-only, requires Node.js 16+). It provides a `lintRule` function that takes metadata and a rule callback, handling plugin registration, error messages via VFile, and severity levels. Key differentiators: reduces boilerplate for unified lint rule authors, supports both sync and async rules, includes TypeScript types, and is part of the official remark-lint family.","status":"active","version":"3.0.1","language":"javascript","source_language":"en","source_url":"https://github.com/remarkjs/remark-lint#main","tags":["javascript","lint","plugin","remark-lint","rule","unified","unified-plugin","typescript"],"install":[{"cmd":"npm install unified-lint-rule","lang":"bash","label":"npm"},{"cmd":"yarn add unified-lint-rule","lang":"bash","label":"yarn"},{"cmd":"pnpm add unified-lint-rule","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Package is ESM-only since v3; require() throws ERR_REQUIRE_ESM.","wrong":"const { lintRule } = require('unified-lint-rule')","symbol":"lintRule","correct":"import { lintRule } from 'unified-lint-rule'"}],"quickstart":{"code":"import { lintRule } from 'unified-lint-rule'\n\nconst remarkLintFileExtension = lintRule(\n  'remark-lint:file-extension',\n  function (tree, file, options) {\n    const ext = file.extname\n    const option = options || 'md'\n    if (ext && ext.slice(1) !== option) {\n      file.message('Incorrect extension: use `' + option + '`')\n    }\n  }\n)\n\nexport default remarkLintFileExtension\n\n// Usage with unified:\n// import { unified } from 'unified'\n// import remarkParse from 'remark-parse'\n// import remarkStringify from 'remark-stringify'\n// import remarkLintFileExtension from './my-lint-rule.js'\n// const file = await unified().use(remarkParse).use(remarkLintFileExtension, 'md').process('')\n// console.log(file.messages)","lang":"typescript","description":"Creates a custom rule that checks file extension, showing the minimal API to build a lint rule."},"warnings":[{"fix":"Switch to ES module syntax (import) and ensure package.json has \"type\": \"module\" or use .mjs extension.","message":"ESM-only: Node.js 16+ required. CommonJS require() will fail with ERR_REQUIRE_ESM.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Define rule with exactly 3 parameters for sync, or 4 parameters (including `Next`) for async, and always call next() to avoid hanging.","message":"The rule function's fourth parameter is the `Next` callback for async rules; omitting it makes the rule synchronous. If you need async, you must accept a fourth parameter and call it when done.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Check for undefined options and provide defaults explicitly (e.g., `const opts = options || 'md'`).","message":"Options are passed as the third argument to the rule function. If the rule is configured with no options, the value is `undefined`. Default handling is manual.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your unified version is compatible (>=10). No code changes needed if using unified's .use().","message":"In unified-lint-rule v2, the `lintRule` function returned a plugin with a different signature. In v3, the return is a standard unified plugin.","severity":"deprecated","affected_versions":">=3.0.0"}],"env_vars":null,"last_verified":"2026-05-01T00:00:00.000Z","next_check":"2026-07-30T00:00:00.000Z","problems":[{"fix":"Convert to ES module syntax: use `import { lintRule } from 'unified-lint-rule'` and set \"type\": \"module\" in package.json.","cause":"Using CommonJS require() on an ESM-only package.","error":"ERR_REQUIRE_ESM"},{"fix":"Ensure the first argument to `file.message` is a string describing the lint error: `file.message('Incorrect extension: use `' + option + '`')`.","cause":"Calling `file.message()` incorrectly (e.g., passing options as first argument without string).","error":"TypeError: (intermediate value).message is not a function"},{"fix":"Provide a properly formatted origin string like 'remark-lint:my-rule' (must contain a colon).","cause":"Passing invalid metadata to `lintRule` (e.g., missing colon in origin or non-string).","error":"Error: Expected a `origin` string"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}