or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-remark-lint-no-duplicate-definitions

remark-lint rule to warn when identifiers are defined multiple times in Markdown documents

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/remark-lint-no-duplicate-definitions@3.1.x

To install, run

npx @tessl/cli install tessl/npm-remark-lint-no-duplicate-definitions@3.1.0

index.mddocs/

remark-lint-no-duplicate-definitions

remark-lint-no-duplicate-definitions is a remark-lint rule plugin that warns when identifiers are defined multiple times in Markdown documents. It integrates with the unified ecosystem to detect duplicate link reference definitions and footnote definitions, helping maintain clean and error-free Markdown by catching potential conflicts that could lead to ambiguous references.

This package is built using the unified-lint-rule wrapper and follows the standard remark-lint plugin patterns for consistent error reporting and integration with the remark processing pipeline.

Package Information

  • Package Name: remark-lint-no-duplicate-definitions
  • Package Type: npm
  • Language: JavaScript (ES modules)
  • Installation: npm install remark-lint-no-duplicate-definitions

Core Imports

import remarkLintNoDuplicateDefinitions from 'remark-lint-no-duplicate-definitions';

For CommonJS (not supported - ESM only):

// Not supported - package is ESM only

Complete imports for typical usage:

import {unified} from 'unified';
import remarkParse from 'remark-parse';
import remarkLint from 'remark-lint';
import remarkLintNoDuplicateDefinitions from 'remark-lint-no-duplicate-definitions';
import remarkStringify from 'remark-stringify';
import {read} from 'to-vfile';
import {reporter} from 'vfile-reporter';

Basic Usage

import {unified} from 'unified';
import remarkParse from 'remark-parse';
import remarkLint from 'remark-lint';
import remarkLintNoDuplicateDefinitions from 'remark-lint-no-duplicate-definitions';
import remarkStringify from 'remark-stringify';
import {read} from 'to-vfile';
import {reporter} from 'vfile-reporter';

const file = await read('example.md');

await unified()
  .use(remarkParse)
  .use(remarkLint)
  .use(remarkLintNoDuplicateDefinitions)
  .use(remarkStringify)
  .process(file);

console.error(reporter(file));

Capabilities

Lint Rule Plugin

The main and only export of this package is a unified plugin function created using unified-lint-rule that provides a remark-lint rule for detecting duplicate definitions.

/**
 * remark-lint rule to warn when identifiers are defined multiple times
 * Created using unified-lint-rule wrapper with origin 'remark-lint:no-duplicate-definitions'
 * @returns Transform function (Transformer from unified)
 */
function remarkLintNoDuplicateDefinitions(): Transformer;

Parameters: None (the rule takes no configuration options)

Returns: Transform function that can be used with unified processors

Implementation: This plugin is created using the lintRule function from unified-lint-rule with the configuration:

  • Origin: 'remark-lint:no-duplicate-definitions'
  • URL: Documentation URL for the rule
  • Rule function: Processes the markdown AST to detect duplicate definitions

Detection Capabilities:

  • Link reference definitions: Detects when [identifier]: url is defined multiple times
  • Footnote definitions: Detects when [^identifier]: content is defined multiple times (GFM/GitHub Flavored Markdown)

Error Messages:

  • For duplicate link definitions: "Unexpected definition with an already defined identifier (identifier), expected unique identifiers"
  • For duplicate footnote definitions: "Unexpected footnote definition with an already defined identifier (identifier), expected unique identifiers"

Usage Examples

Valid Markdown (No Warnings)

[mercury]: https://example.com/mercury/
[venus]: https://example.com/venus/

Invalid Markdown (Produces Warning)

[mercury]: https://example.com/mercury/
[mercury]: https://example.com/venus/

Warning: 2:1-2:38: Unexpected definition with an already defined identifier (mercury), expected unique identifiers

Footnote Definitions (GFM)

Mercury[^mercury].

[^mercury]:
  Mercury is the first planet from the Sun and the smallest in the Solar System.

[^mercury]:
  Venus is the second planet from the Sun.

Warning: 7:1-7:12: Unexpected footnote definition with an already defined identifier (mercury), expected unique identifiers

Integration

CLI Usage

remark --frail --use remark-lint --use remark-lint-no-duplicate-definitions .

Configuration File

{
  "remarkConfig": {
    "plugins": [
      "remark-lint",
      "remark-lint-no-duplicate-definitions"
    ]
  }
}

Types

This package is written in JavaScript but includes TypeScript type definitions (published as index.d.ts). It follows the unified ecosystem patterns:

// TypeScript definitions are available
import type {Transformer} from 'unified';
import type {Root} from 'mdast';
import type {Nodes} from 'mdast';

// The plugin function signature
function remarkLintNoDuplicateDefinitions(): Transformer<Root>;

// Internal types used by the implementation
type DefinitionNode = Extract<Nodes, {type: 'definition'}>;
type FootnoteDefinitionNode = Extract<Nodes, {type: 'footnoteDefinition'}>;

Type Dependencies

The implementation uses these key type imports:

import type {Nodes, Root} from 'mdast';
// From the source code internal types

Error Handling

The plugin creates VFileMessage objects with detailed information:

  • Location: Precise position information for both original and duplicate definitions
  • Context: Full ancestor tree information for better error reporting
  • Cause: References to the original definition location using nested VFileMessage
  • Source: Always marked as 'remark-lint' with rule ID 'no-duplicate-definitions'

VFileMessage Structure

When duplicate definitions are found, the plugin creates messages with this structure:

// Primary error message
file.message(
  'Unexpected [footnote ]definition with an already defined identifier (`identifier`), expected unique identifiers',
  {
    ancestors: [...parents, node], // Full ancestry chain
    cause: new VFileMessage('Identifier already defined here', {
      ancestors: duplicateAncestors, // Original definition ancestry
      place: duplicate.position,     // Original definition position
      source: 'remark-lint',
      ruleId: 'no-duplicate-definitions'
    }),
    place: node.position // Current duplicate position
  }
);

Implementation Notes

  • Performance: Skips phrasing content during AST traversal using mdast-util-phrasing for optimal performance
  • Scope: Only processes definition and footnoteDefinition nodes
  • Tracking: Maintains separate Map<string, Array<Nodes>> objects for regular definitions and footnote definitions
  • Ancestry: Preserves full parent chain information for detailed error reporting
  • Traversal: Uses unist-util-visit-parents for efficient AST walking with ancestor tracking
  • Assertion: Uses devlop package for development-time assertions

Dependencies Used

The implementation relies on these core dependencies:

import {ok as assert} from 'devlop';                    // Development assertions
import {phrasing} from 'mdast-util-phrasing';           // Skip phrasing content
import {lintRule} from 'unified-lint-rule';             // Lint rule wrapper
import {SKIP, visitParents} from 'unist-util-visit-parents'; // AST traversal
import {VFileMessage} from 'vfile-message';             // Error message creation

This rule is part of the remark-preset-lint-recommended preset and integrates seamlessly with other remark-lint rules and the broader unified ecosystem.