unified-lint-rule

raw JSON →
3.0.1 verified Fri May 01 auth: no javascript

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.

error ERR_REQUIRE_ESM
cause Using CommonJS require() on an ESM-only package.
fix
Convert to ES module syntax: use import { lintRule } from 'unified-lint-rule' and set "type": "module" in package.json.
error TypeError: (intermediate value).message is not a function
cause Calling `file.message()` incorrectly (e.g., passing options as first argument without string).
fix
Ensure the first argument to file.message is a string describing the lint error: file.message('Incorrect extension: use ' + option + '').
error Error: Expected a `origin` string
cause Passing invalid metadata to `lintRule` (e.g., missing colon in origin or non-string).
fix
Provide a properly formatted origin string like 'remark-lint:my-rule' (must contain a colon).
breaking ESM-only: Node.js 16+ required. CommonJS require() will fail with ERR_REQUIRE_ESM.
fix Switch to ES module syntax (import) and ensure package.json has "type": "module" or use .mjs extension.
gotcha 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.
fix Define rule with exactly 3 parameters for sync, or 4 parameters (including `Next`) for async, and always call next() to avoid hanging.
gotcha 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.
fix Check for undefined options and provide defaults explicitly (e.g., `const opts = options || 'md'`).
deprecated In unified-lint-rule v2, the `lintRule` function returned a plugin with a different signature. In v3, the return is a standard unified plugin.
fix Ensure your unified version is compatible (>=10). No code changes needed if using unified's .use().
npm install unified-lint-rule
yarn add unified-lint-rule
pnpm add unified-lint-rule

Creates a custom rule that checks file extension, showing the minimal API to build a lint rule.

import { lintRule } from 'unified-lint-rule'

const remarkLintFileExtension = lintRule(
  'remark-lint:file-extension',
  function (tree, file, options) {
    const ext = file.extname
    const option = options || 'md'
    if (ext && ext.slice(1) !== option) {
      file.message('Incorrect extension: use `' + option + '`')
    }
  }
)

export default remarkLintFileExtension

// Usage with unified:
// import { unified } from 'unified'
// import remarkParse from 'remark-parse'
// import remarkStringify from 'remark-stringify'
// import remarkLintFileExtension from './my-lint-rule.js'
// const file = await unified().use(remarkParse).use(remarkLintFileExtension, 'md').process('')
// console.log(file.messages)