or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# remark-lint-no-duplicate-definitions

1

2

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.

3

4

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.

5

6

## Package Information

7

8

- **Package Name**: remark-lint-no-duplicate-definitions

9

- **Package Type**: npm

10

- **Language**: JavaScript (ES modules)

11

- **Installation**: `npm install remark-lint-no-duplicate-definitions`

12

13

## Core Imports

14

15

```javascript

16

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

17

```

18

19

For CommonJS (not supported - ESM only):

20

```javascript

21

// Not supported - package is ESM only

22

```

23

24

Complete imports for typical usage:

25

```javascript

26

import {unified} from 'unified';

27

import remarkParse from 'remark-parse';

28

import remarkLint from 'remark-lint';

29

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

30

import remarkStringify from 'remark-stringify';

31

import {read} from 'to-vfile';

32

import {reporter} from 'vfile-reporter';

33

```

34

35

## Basic Usage

36

37

```javascript

38

import {unified} from 'unified';

39

import remarkParse from 'remark-parse';

40

import remarkLint from 'remark-lint';

41

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

42

import remarkStringify from 'remark-stringify';

43

import {read} from 'to-vfile';

44

import {reporter} from 'vfile-reporter';

45

46

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

47

48

await unified()

49

.use(remarkParse)

50

.use(remarkLint)

51

.use(remarkLintNoDuplicateDefinitions)

52

.use(remarkStringify)

53

.process(file);

54

55

console.error(reporter(file));

56

```

57

58

## Capabilities

59

60

### Lint Rule Plugin

61

62

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.

63

64

```javascript { .api }

65

/**

66

* remark-lint rule to warn when identifiers are defined multiple times

67

* Created using unified-lint-rule wrapper with origin 'remark-lint:no-duplicate-definitions'

68

* @returns Transform function (Transformer from unified)

69

*/

70

function remarkLintNoDuplicateDefinitions(): Transformer;

71

```

72

73

**Parameters**: None (the rule takes no configuration options)

74

75

**Returns**: Transform function that can be used with unified processors

76

77

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

78

- **Origin**: `'remark-lint:no-duplicate-definitions'`

79

- **URL**: Documentation URL for the rule

80

- **Rule function**: Processes the markdown AST to detect duplicate definitions

81

82

**Detection Capabilities**:

83

- **Link reference definitions**: Detects when `[identifier]: url` is defined multiple times

84

- **Footnote definitions**: Detects when `[^identifier]: content` is defined multiple times (GFM/GitHub Flavored Markdown)

85

86

**Error Messages**:

87

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

88

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

89

90

## Usage Examples

91

92

### Valid Markdown (No Warnings)

93

94

```markdown

95

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

96

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

97

```

98

99

### Invalid Markdown (Produces Warning)

100

101

```markdown

102

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

103

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

104

```

105

106

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

107

108

### Footnote Definitions (GFM)

109

110

```markdown

111

Mercury[^mercury].

112

113

[^mercury]:

114

Mercury is the first planet from the Sun and the smallest in the Solar System.

115

116

[^mercury]:

117

Venus is the second planet from the Sun.

118

```

119

120

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

121

122

## Integration

123

124

### CLI Usage

125

126

```bash

127

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

128

```

129

130

### Configuration File

131

132

```json

133

{

134

"remarkConfig": {

135

"plugins": [

136

"remark-lint",

137

"remark-lint-no-duplicate-definitions"

138

]

139

}

140

}

141

```

142

143

## Types

144

145

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

146

147

```typescript { .api }

148

// TypeScript definitions are available

149

import type {Transformer} from 'unified';

150

import type {Root} from 'mdast';

151

import type {Nodes} from 'mdast';

152

153

// The plugin function signature

154

function remarkLintNoDuplicateDefinitions(): Transformer<Root>;

155

156

// Internal types used by the implementation

157

type DefinitionNode = Extract<Nodes, {type: 'definition'}>;

158

type FootnoteDefinitionNode = Extract<Nodes, {type: 'footnoteDefinition'}>;

159

```

160

161

### Type Dependencies

162

163

The implementation uses these key type imports:

164

```typescript { .api }

165

import type {Nodes, Root} from 'mdast';

166

// From the source code internal types

167

```

168

169

## Error Handling

170

171

The plugin creates VFileMessage objects with detailed information:

172

- **Location**: Precise position information for both original and duplicate definitions

173

- **Context**: Full ancestor tree information for better error reporting

174

- **Cause**: References to the original definition location using nested VFileMessage

175

- **Source**: Always marked as 'remark-lint' with rule ID 'no-duplicate-definitions'

176

177

### VFileMessage Structure

178

179

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

180

```javascript { .api }

181

// Primary error message

182

file.message(

183

'Unexpected [footnote ]definition with an already defined identifier (`identifier`), expected unique identifiers',

184

{

185

ancestors: [...parents, node], // Full ancestry chain

186

cause: new VFileMessage('Identifier already defined here', {

187

ancestors: duplicateAncestors, // Original definition ancestry

188

place: duplicate.position, // Original definition position

189

source: 'remark-lint',

190

ruleId: 'no-duplicate-definitions'

191

}),

192

place: node.position // Current duplicate position

193

}

194

);

195

```

196

197

## Implementation Notes

198

199

- **Performance**: Skips phrasing content during AST traversal using `mdast-util-phrasing` for optimal performance

200

- **Scope**: Only processes `definition` and `footnoteDefinition` nodes

201

- **Tracking**: Maintains separate `Map<string, Array<Nodes>>` objects for regular definitions and footnote definitions

202

- **Ancestry**: Preserves full parent chain information for detailed error reporting

203

- **Traversal**: Uses `unist-util-visit-parents` for efficient AST walking with ancestor tracking

204

- **Assertion**: Uses `devlop` package for development-time assertions

205

206

### Dependencies Used

207

208

The implementation relies on these core dependencies:

209

```javascript { .api }

210

import {ok as assert} from 'devlop'; // Development assertions

211

import {phrasing} from 'mdast-util-phrasing'; // Skip phrasing content

212

import {lintRule} from 'unified-lint-rule'; // Lint rule wrapper

213

import {SKIP, visitParents} from 'unist-util-visit-parents'; // AST traversal

214

import {VFileMessage} from 'vfile-message'; // Error message creation

215

```

216

217

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