@entro314labs/markdownfix
Version:
Opinionated markdown formatter and linter for MD, MDX, MDC, and MDD files using Remark/Unified ecosystem
390 lines (276 loc) • 9.46 kB
Markdown
# ESLint + MDX Integration Guide
This project integrates `eslint-plugin-mdx` with the existing remark-lint setup to provide comprehensive linting for MDX files.
## Why ESLint for MDX?
While remark-lint handles markdown syntax and formatting, ESLint adds:
- **JavaScript/JSX linting** - Lint code inside MDX code blocks
- **IDE integration** - Better VS Code support with ESLint extension
- **Unified error reporting** - Consistent error format across tools
- **Code quality checks** - Catch unused variables, syntax errors in examples
- **Built-in by default** - No extra installation needed, opinionated and ready to use
## Architecture
```
┌─────────────────────────────────────────────────┐
│ Your MDX/Markdown Files │
└─────────────────────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ remark-cli │ │ eslint-plugin- │
│ │ │ mdx │
│ • Formatting │ │ │
│ • MD syntax │ │ • JS/JSX linting │
│ • 40+ rules │ │ • Reads .remarkrc│
└──────────────┘ │ • Code blocks │
└──────────────────┘
```
## How It Works
1. **remark-cli** - Primary formatter and markdown linter
- Uses [.remarkrc.js](./.remarkrc.js) configuration
- Handles all markdown syntax and formatting
- Fixes issues automatically with `--output`
2. **eslint-plugin-mdx** - Complementary JavaScript linter
- Reads [eslint.config.js](./eslint.config.js) (ESLint 9 flat config)
- **Automatically uses remark-lint rules** from `.remarkrc.js`
- Lints JavaScript/JSX code in MDX code blocks
- Provides IDE integration
## Installation
### Global Installation (Recommended)
Install `markdownfix` globally - **ESLint support is built-in**:
```bash
npm install -g @entro314labs/markdownfix
# or
pnpm add -g @entro314labs/markdownfix
```
Then use anywhere:
```bash
cd your-project
mdfix nuclear
```
**ESLint is included by default:**
- ✅ `eslint` and `eslint-plugin-mdx` are bundled dependencies
- ✅ Works out of the box - no additional installation needed
- ✅ Uses bundled config automatically
- ✅ Override by creating local `eslint.config.js`
### Local Installation (Project-specific)
```bash
npm install -D @entro314labs/markdownfix
# or
pnpm add -D @entro314labs/markdownfix
```
ESLint dependencies are included automatically.
## Configuration Files
### [eslint.config.js](./eslint.config.js)
ESLint 9 flat config that:
- Configures MDX plugin for `.md`, `.mdx`, `.mdd` files
- Uses `mdx/remark` rule to integrate remark-lint
- Enables code block linting
- Defines globals for documentation examples
**Note:** When `markdownfix` is installed (globally or locally):
- ✅ ESLint dependencies are **always included** (opinionated approach)
- ✅ Uses local `eslint.config.js` if it exists
- ✅ Falls back to bundled config if not found
- ℹ️ Shows a message when using bundled config
### [.remarkrc.js](./.remarkrc.js)
Existing remark configuration with 40+ lint rules. This is **automatically used** by ESLint via the `mdx/remark` rule.
## Available Scripts
```bash
# Markdown formatting (remark-cli)
pnpm run format # Auto-fix markdown formatting
pnpm run format:check # Check without writing changes
# Linting
pnpm run lint # Remark-lint only
pnpm run lint:eslint # ESLint + MDX only
pnpm run lint:eslint:fix # ESLint auto-fix
pnpm run lint:all # Both remark and ESLint
# Complete workflow
pnpm run process # Format + lint all
pnpm run process:safe # Check + lint all
pnpm run nuclear # 🚀 Run ALL linters and fixers
pnpm test # Same as process:safe
# CLI usage
markdownfix nuclear # Nuclear mode via CLI
mdfix nuclear --quiet # Silent nuclear mode
```
## Workflow
### Recommended Development Workflow
#### Quick Fix Everything (Recommended)
```bash
# 🚀 One command to rule them all
markdownfix nuclear
```
This runs the complete 4-step workflow:
1. Remark formatting
2. Remark linting
3. ESLint auto-fix
4. ESLint linting
#### Manual Step-by-Step
1. **Write/edit markdown files**
2. **Format with remark**
```bash
pnpm run format
```
3. **Lint with both tools**
```bash
pnpm run lint:all
```
4. **Or use the complete workflow**
```bash
pnpm run process
```
### CI/CD Workflow
```bash
pnpm test
```
This runs `process:safe` which:
1. Checks formatting (no writes)
2. Runs remark-lint
3. Runs ESLint
## What Gets Checked
### Remark-lint (40+ rules)
- Markdown syntax (headings, lists, tables)
- Formatting consistency (emphasis, strong, code blocks)
- Link validation
- Table alignment
- Line length
- Trailing spaces
- Final newlines
See [.remarkrc.js](./.remarkrc.js) for full configuration.
### ESLint (JavaScript in code blocks)
- `no-var` - Enforce const/let
- `prefer-const` - Use const when possible
- `no-unused-vars` - Warn about unused variables
- Syntax errors in code examples
## IDE Integration
### VS Code
1. **Install ESLint extension**
```
ext install dbaeumer.vscode-eslint
```
2. **Configure workspace settings** (`.vscode/settings.json`)
```json
{
"eslint.validate": [
"javascript",
"typescript",
"markdown",
"mdx"
],
"eslint.probe": [
"javascript",
"typescript",
"markdown",
"mdx"
]
}
```
3. **MDX files will show inline errors** from both remark-lint and ESLint
## Examples
### Catching Code Block Issues
**Before:**
```javascript
function example() {
var unused = "bad";
return "hello"
}
```
**ESLint warnings:**
- `no-var`: Unexpected var, use let or const instead
- `no-unused-vars`: 'unused' is assigned but never used
**After:**
```javascript
function greet(name) {
return `Hello ${name}`;
}
console.log(greet("World"));
```
### Markdown Issues (remark-lint)
**Before:**
```markdown
#No Space After Hash
- item 1
- item 2
- nested
```
**Remark-lint errors:**
- Headings must have space after `#`
- List items need blank lines between them
**After:**
```markdown
# Proper Heading
- item 1
- item 2
- nested
```
## Ignoring Files
Files are ignored via:
1. **ESLint** - `ignores` array in [eslint.config.js](./eslint.config.js)
2. **Remark** - [.remarkignore](./.remarkignore)
Common ignored files:
- `README.md`
- `CHANGELOG.md`
- `LICENSE`
- `node_modules/`
- Build outputs
## Troubleshooting
### ESLint not finding MDX files
Make sure you're using the correct extension flag:
```bash
# Correct
eslint --ext .md,.mdx,.mdd .
# Wrong (won't work)
eslint .
```
### Remark-lint rules not appearing in ESLint
The `mdx/remark` rule automatically reads `.remarkrc.js`. If changes don't appear:
1. Restart your IDE/ESLint server
2. Check `.remarkrc.js` syntax is valid
3. Verify `mdx/remark` rule is enabled in `eslint.config.js`
### Code block linting not working
Ensure code blocks have language identifiers:
```javascript
// This will be linted
const x = 1;
```
### Performance
For large projects, you can:
1. **Disable code block linting**
```javascript
// In eslint.config.js
processor: mdxPlugin.createRemarkProcessor({
lintCodeBlocks: false
})
```
2. **Run tools separately**
```bash
pnpm run lint # Just remark
pnpm run lint:eslint # Just ESLint
```
## Comparison with Alternatives
### Why not just remark-cli?
Remark-cli is excellent for markdown formatting but doesn't lint JavaScript code in code blocks.
### Why not just ESLint?
ESLint alone doesn't understand markdown-specific rules like table formatting, heading hierarchy, etc.
### Why not Biome?
As of 2025, Biome does not support MDX or stable Markdown linting. Markdown support is on their roadmap but not yet available.
### Why not Prettier?
Prettier formats but doesn't lint. This project uses remark for both formatting and linting with 40+ opinionated rules.
## Benefits of This Setup
✅ **Comprehensive** - Both markdown and JavaScript linting
✅ **IDE integration** - Real-time feedback in VS Code
✅ **Automatic fixes** - Most issues can be auto-fixed
✅ **Unified workflow** - Single `pnpm test` command
✅ **Flexible** - Can use tools separately or together
✅ **No conflicts** - ESLint uses remark rules, no duplication
## Migration Notes
If you were using only remark-cli before:
1. ✅ All existing remark rules still work
2. ✅ All existing scripts still work
3. ✅ New ESLint scripts are additive
4. ✅ No breaking changes to workflow
## Further Reading
- [eslint-plugin-mdx documentation](https://github.com/mdx-js/eslint-mdx)
- [remark-lint rules](https://github.com/remarkjs/remark-lint)
- [ESLint flat config](https://eslint.org/docs/latest/use/configure/)
- [MDX documentation](https://mdxjs.com/)