@entro314labs/markdownfix 0.0.7 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.remarkignore CHANGED
@@ -56,4 +56,6 @@ coverage/
56
56
  # Specific files to ignore
57
57
  CHANGELOG.md
58
58
  LICENSE
59
- README.md
59
+ README.md
60
+ PUBLISHING.md
61
+ ESLINT_INTEGRATION.md
package/.remarkrc.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Opinionated Remark configuration for markdown processing
3
- * Supports .md, and .mdx files with consistent formatting
3
+ * Supports .md, .mdx, and .mdc files with consistent formatting
4
4
  * Optionally supports .mdd files if mdd package is installed
5
5
  */
6
6
 
@@ -18,7 +18,7 @@ try {
18
18
  ];
19
19
  console.log('✓ MDD support enabled');
20
20
  } catch (e) {
21
- // MDD package not installed - only support .md and .mdx
21
+ // MDD package not installed - only support .md, .mdx, and .mdc
22
22
  mddPlugins = ['remark-mdx'];
23
23
  console.log('ℹ MDD support not available (install mdd package for .mdd file support)');
24
24
  }
@@ -50,6 +50,9 @@ export default {
50
50
  // Enable GitHub Flavored Markdown (tables, strikethrough, etc.)
51
51
  'remark-gfm',
52
52
 
53
+ // Enable MDC syntax (Markdown Components for Nuxt Content)
54
+ 'remark-mdc',
55
+
53
56
  // MDX/MDD plugins (loaded dynamically above)
54
57
  ...mddPlugins,
55
58
 
@@ -76,8 +79,6 @@ export default {
76
79
  ['remark-lint-final-newline', true],
77
80
  ['remark-lint-hard-break-spaces', true],
78
81
  ['remark-lint-no-empty-sections', true],
79
- // Allow .md, .mdx, and .mdd file extensions
80
- ['remark-lint-file-extension', ['md', 'mdx', 'mdd']],
81
82
 
82
83
  // Must be last - handles the output formatting
83
84
  'remark-stringify'
@@ -0,0 +1,382 @@
1
+ # ESLint + MDX Integration Guide
2
+
3
+ This project integrates `eslint-plugin-mdx` with the existing remark-lint setup to provide comprehensive linting for MDX files.
4
+
5
+ ## Why ESLint for MDX?
6
+
7
+ While remark-lint handles markdown syntax and formatting, ESLint adds:
8
+
9
+ - **JavaScript/JSX linting** - Lint code inside MDX code blocks
10
+ - **IDE integration** - Better VS Code support with ESLint extension
11
+ - **Unified error reporting** - Consistent error format across tools
12
+ - **Code quality checks** - Catch unused variables, syntax errors in examples
13
+
14
+ ## Architecture
15
+
16
+ ```
17
+ ┌─────────────────────────────────────────────────┐
18
+ │ Your MDX/Markdown Files │
19
+ └─────────────────────────────────────────────────┘
20
+
21
+ ┌───────────┴───────────┐
22
+ │ │
23
+ ▼ ▼
24
+ ┌──────────────┐ ┌──────────────────┐
25
+ │ remark-cli │ │ eslint-plugin- │
26
+ │ │ │ mdx │
27
+ │ • Formatting │ │ │
28
+ │ • MD syntax │ │ • JS/JSX linting │
29
+ │ • 40+ rules │ │ • Reads .remarkrc│
30
+ └──────────────┘ │ • Code blocks │
31
+ └──────────────────┘
32
+ ```
33
+
34
+ ## How It Works
35
+
36
+ 1. **remark-cli** - Primary formatter and markdown linter
37
+ - Uses [.remarkrc.js](./.remarkrc.js) configuration
38
+ - Handles all markdown syntax and formatting
39
+ - Fixes issues automatically with `--output`
40
+
41
+ 2. **eslint-plugin-mdx** - Complementary JavaScript linter
42
+ - Reads [eslint.config.js](./eslint.config.js) (ESLint 9 flat config)
43
+ - **Automatically uses remark-lint rules** from `.remarkrc.js`
44
+ - Lints JavaScript/JSX code in MDX code blocks
45
+ - Provides IDE integration
46
+
47
+ ## Installation
48
+
49
+ ### Local Installation (Project-specific)
50
+
51
+ ```bash
52
+ pnpm add -D eslint eslint-plugin-mdx eslint-plugin-react
53
+ ```
54
+
55
+ ### Global Installation (Recommended)
56
+
57
+ Install `markdownfix` globally to use across all projects:
58
+
59
+ ```bash
60
+ npm install -g @entro314labs/markdownfix
61
+ # or
62
+ pnpm add -g @entro314labs/markdownfix
63
+ ```
64
+
65
+ Then use anywhere:
66
+
67
+ ```bash
68
+ cd your-project
69
+ mdfix nuclear
70
+ ```
71
+
72
+ The tool will:
73
+
74
+ - ✅ Use your local `eslint.config.js` if it exists
75
+ - ✅ Fall back to bundled ESLint config if not found
76
+ - ✅ Always respect your local `.remarkrc.js` if present
77
+
78
+ ## Configuration Files
79
+
80
+ ### [eslint.config.js](./eslint.config.js)
81
+
82
+ ESLint 9 flat config that:
83
+
84
+ - Configures MDX plugin for `.md`, `.mdx`, `.mdd` files
85
+ - Uses `mdx/remark` rule to integrate remark-lint
86
+ - Enables code block linting
87
+ - Defines globals for documentation examples
88
+
89
+ **Note:** When `markdownfix` is installed globally and run in a project:
90
+
91
+ - ✅ Uses local `eslint.config.js` if it exists
92
+ - ✅ Falls back to bundled config if not found
93
+ - ℹ️ Shows a message when using bundled config
94
+
95
+ ### [.remarkrc.js](./.remarkrc.js)
96
+
97
+ Existing remark configuration with 40+ lint rules. This is **automatically used** by ESLint via the `mdx/remark` rule.
98
+
99
+ ## Available Scripts
100
+
101
+ ```bash
102
+ # Markdown formatting (remark-cli)
103
+ pnpm run format # Auto-fix markdown formatting
104
+ pnpm run format:check # Check without writing changes
105
+
106
+ # Linting
107
+ pnpm run lint # Remark-lint only
108
+ pnpm run lint:eslint # ESLint + MDX only
109
+ pnpm run lint:eslint:fix # ESLint auto-fix
110
+ pnpm run lint:all # Both remark and ESLint
111
+
112
+ # Complete workflow
113
+ pnpm run process # Format + lint all
114
+ pnpm run process:safe # Check + lint all
115
+ pnpm run nuclear # 🚀 Run ALL linters and fixers
116
+ pnpm test # Same as process:safe
117
+
118
+ # CLI usage
119
+ markdownfix nuclear # Nuclear mode via CLI
120
+ mdfix nuclear --quiet # Silent nuclear mode
121
+ ```
122
+
123
+ ## Workflow
124
+
125
+ ### Recommended Development Workflow
126
+
127
+ #### Quick Fix Everything (Recommended)
128
+
129
+ ```bash
130
+ # 🚀 One command to rule them all
131
+ markdownfix nuclear
132
+ ```
133
+
134
+ This runs the complete 4-step workflow:
135
+
136
+ 1. Remark formatting
137
+ 2. Remark linting
138
+ 3. ESLint auto-fix
139
+ 4. ESLint linting
140
+
141
+ #### Manual Step-by-Step
142
+
143
+ 1. **Write/edit markdown files**
144
+
145
+ 2. **Format with remark**
146
+ ```bash
147
+ pnpm run format
148
+ ```
149
+
150
+ 3. **Lint with both tools**
151
+ ```bash
152
+ pnpm run lint:all
153
+ ```
154
+
155
+ 4. **Or use the complete workflow**
156
+ ```bash
157
+ pnpm run process
158
+ ```
159
+
160
+ ### CI/CD Workflow
161
+
162
+ ```bash
163
+ pnpm test
164
+ ```
165
+
166
+ This runs `process:safe` which:
167
+
168
+ 1. Checks formatting (no writes)
169
+ 2. Runs remark-lint
170
+ 3. Runs ESLint
171
+
172
+ ## What Gets Checked
173
+
174
+ ### Remark-lint (40+ rules)
175
+
176
+ - Markdown syntax (headings, lists, tables)
177
+ - Formatting consistency (emphasis, strong, code blocks)
178
+ - Link validation
179
+ - Table alignment
180
+ - Line length
181
+ - Trailing spaces
182
+ - Final newlines
183
+
184
+ See [.remarkrc.js](./.remarkrc.js) for full configuration.
185
+
186
+ ### ESLint (JavaScript in code blocks)
187
+
188
+ - `no-var` - Enforce const/let
189
+ - `prefer-const` - Use const when possible
190
+ - `no-unused-vars` - Warn about unused variables
191
+ - Syntax errors in code examples
192
+
193
+ ## IDE Integration
194
+
195
+ ### VS Code
196
+
197
+ 1. **Install ESLint extension**
198
+ ```
199
+ ext install dbaeumer.vscode-eslint
200
+ ```
201
+
202
+ 2. **Configure workspace settings** (`.vscode/settings.json`)
203
+ ```json
204
+ {
205
+ "eslint.validate": [
206
+ "javascript",
207
+ "typescript",
208
+ "markdown",
209
+ "mdx"
210
+ ],
211
+ "eslint.probe": [
212
+ "javascript",
213
+ "typescript",
214
+ "markdown",
215
+ "mdx"
216
+ ]
217
+ }
218
+ ```
219
+
220
+ 3. **MDX files will show inline errors** from both remark-lint and ESLint
221
+
222
+ ## Examples
223
+
224
+ ### Catching Code Block Issues
225
+
226
+ **Before:**
227
+
228
+ ```javascript
229
+ function example() {
230
+ var unused = "bad";
231
+ return "hello"
232
+ }
233
+ ```
234
+
235
+ **ESLint warnings:**
236
+
237
+ - `no-var`: Unexpected var, use let or const instead
238
+ - `no-unused-vars`: 'unused' is assigned but never used
239
+
240
+ **After:**
241
+
242
+ ```javascript
243
+ function greet(name) {
244
+ return `Hello ${name}`;
245
+ }
246
+
247
+ console.log(greet("World"));
248
+ ```
249
+
250
+ ### Markdown Issues (remark-lint)
251
+
252
+ **Before:**
253
+
254
+ ```markdown
255
+ #No Space After Hash
256
+ - item 1
257
+ - item 2
258
+ - nested
259
+ ```
260
+
261
+ **Remark-lint errors:**
262
+
263
+ - Headings must have space after `#`
264
+ - List items need blank lines between them
265
+
266
+ **After:**
267
+
268
+ ```markdown
269
+ # Proper Heading
270
+
271
+ - item 1
272
+
273
+ - item 2
274
+ - nested
275
+ ```
276
+
277
+ ## Ignoring Files
278
+
279
+ Files are ignored via:
280
+
281
+ 1. **ESLint** - `ignores` array in [eslint.config.js](./eslint.config.js)
282
+ 2. **Remark** - [.remarkignore](./.remarkignore)
283
+
284
+ Common ignored files:
285
+
286
+ - `README.md`
287
+ - `CHANGELOG.md`
288
+ - `LICENSE`
289
+ - `node_modules/`
290
+ - Build outputs
291
+
292
+ ## Troubleshooting
293
+
294
+ ### ESLint not finding MDX files
295
+
296
+ Make sure you're using the correct extension flag:
297
+
298
+ ```bash
299
+ # Correct
300
+ eslint --ext .md,.mdx,.mdd .
301
+
302
+ # Wrong (won't work)
303
+ eslint .
304
+ ```
305
+
306
+ ### Remark-lint rules not appearing in ESLint
307
+
308
+ The `mdx/remark` rule automatically reads `.remarkrc.js`. If changes don't appear:
309
+
310
+ 1. Restart your IDE/ESLint server
311
+ 2. Check `.remarkrc.js` syntax is valid
312
+ 3. Verify `mdx/remark` rule is enabled in `eslint.config.js`
313
+
314
+ ### Code block linting not working
315
+
316
+ Ensure code blocks have language identifiers:
317
+
318
+ ```javascript
319
+ // This will be linted
320
+ const x = 1;
321
+ ```
322
+
323
+ ### Performance
324
+
325
+ For large projects, you can:
326
+
327
+ 1. **Disable code block linting**
328
+ ```javascript
329
+ // In eslint.config.js
330
+ processor: mdxPlugin.createRemarkProcessor({
331
+ lintCodeBlocks: false
332
+ })
333
+ ```
334
+
335
+ 2. **Run tools separately**
336
+ ```bash
337
+ pnpm run lint # Just remark
338
+ pnpm run lint:eslint # Just ESLint
339
+ ```
340
+
341
+ ## Comparison with Alternatives
342
+
343
+ ### Why not just remark-cli?
344
+
345
+ Remark-cli is excellent for markdown formatting but doesn't lint JavaScript code in code blocks.
346
+
347
+ ### Why not just ESLint?
348
+
349
+ ESLint alone doesn't understand markdown-specific rules like table formatting, heading hierarchy, etc.
350
+
351
+ ### Why not Biome?
352
+
353
+ As of 2025, Biome does not support MDX or stable Markdown linting. Markdown support is on their roadmap but not yet available.
354
+
355
+ ### Why not Prettier?
356
+
357
+ Prettier formats but doesn't lint. This project uses remark for both formatting and linting with 40+ opinionated rules.
358
+
359
+ ## Benefits of This Setup
360
+
361
+ ✅ **Comprehensive** - Both markdown and JavaScript linting
362
+ ✅ **IDE integration** - Real-time feedback in VS Code
363
+ ✅ **Automatic fixes** - Most issues can be auto-fixed
364
+ ✅ **Unified workflow** - Single `pnpm test` command
365
+ ✅ **Flexible** - Can use tools separately or together
366
+ ✅ **No conflicts** - ESLint uses remark rules, no duplication
367
+
368
+ ## Migration Notes
369
+
370
+ If you were using only remark-cli before:
371
+
372
+ 1. ✅ All existing remark rules still work
373
+ 2. ✅ All existing scripts still work
374
+ 3. ✅ New ESLint scripts are additive
375
+ 4. ✅ No breaking changes to workflow
376
+
377
+ ## Further Reading
378
+
379
+ - [eslint-plugin-mdx documentation](https://github.com/mdx-js/eslint-mdx)
380
+ - [remark-lint rules](https://github.com/remarkjs/remark-lint)
381
+ - [ESLint flat config](https://eslint.org/docs/latest/use/configure/)
382
+ - [MDX documentation](https://mdxjs.com/)
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Markdown Formatter (markdownfix)
2
2
 
3
- **Opinionated markdown formatter and linter for `.md`, `.mdd`, and `.mdx` files**
3
+ **Opinionated markdown formatter and linter for `.md`, `.mdx`, `.mdc`, and `.mdd` files**
4
4
 
5
5
  Built on the Remark ecosystem with strict, consistent formatting rules for developer documentation, technical writing, and web content. Perfect for README files, technical docs, blogs, and GitHub wikis.
6
6
 
@@ -8,10 +8,13 @@ Built on the Remark ecosystem with strict, consistent formatting rules for devel
8
8
 
9
9
  - ✅ **Opinionated formatting** - Consistent style across all markdown files
10
10
  - ✅ **GitHub Flavored Markdown** - Tables, task lists, strikethrough, autolinks
11
- - ✅ **MDX support** - JSX components in markdown
12
- - ✅ **Comprehensive linting** - 40+ lint rules for quality and consistency
11
+ - ✅ **MDX support** - JSX components in markdown with ESLint integration
12
+ - ✅ **MDC syntax support** - Markdown Components for Nuxt Content
13
+ - ✅ **Comprehensive linting** - 40+ remark-lint rules for quality and consistency
14
+ - ✅ **Code block linting** - ESLint integration for JavaScript/JSX in code blocks
13
15
  - ✅ **Link validation** - Check for broken links
14
16
  - ✅ **Auto-fixing** - Automatically fix formatting issues
17
+ - ✅ **IDE integration** - Works with VS Code ESLint extension
15
18
 
16
19
  ## Installation
17
20
 
@@ -35,6 +38,9 @@ markdownfix check
35
38
  # Lint files for issues
36
39
  markdownfix lint
37
40
 
41
+ # 🚀 Nuclear mode - run ALL linters and fixers
42
+ markdownfix nuclear
43
+
38
44
  # Format specific files
39
45
  markdownfix format README.md docs/*.md
40
46
 
@@ -53,7 +59,8 @@ Add to your `package.json`:
53
59
  {
54
60
  "scripts": {
55
61
  "format:md": "markdownfix format",
56
- "lint:md": "markdownfix lint"
62
+ "lint:md": "markdownfix lint",
63
+ "fix:md": "markdownfix nuclear"
57
64
  }
58
65
  }
59
66
  ```
@@ -103,8 +110,45 @@ markdownfix setup
103
110
  | --------- | ----------- | --------------------------------------- | ------------------------------- |
104
111
  | `.md` | ✅ Full | GFM, frontmatter, tables, task lists | Documentation, READMEs, blogs |
105
112
  | `.mdx` | ✅ Full | Above + JSX components, imports/exports | React docs, interactive content |
113
+ | `.mdc` | ✅ Full | Markdown Components (Nuxt Content) | Nuxt Content, Vue documentation |
106
114
  | `.mdd` | ⚠️ Optional | Business documents (see below) | Invoices, proposals, contracts |
107
115
 
116
+ ### MDC Support
117
+
118
+ This formatter includes **full support for `.mdc` files** and MDC (Markdown Components) syntax via `remark-mdc`. MDC is a superset of Markdown developed by Nuxt that allows you to use Vue-like components.
119
+
120
+ **MDC Features:**
121
+
122
+ ```markdown
123
+ <!-- Block components -->
124
+ ::card
125
+ This is card content with **formatting**.
126
+ ::
127
+
128
+ <!-- Inline components -->
129
+ This is text with an :icon{name="rocket"} inline component.
130
+
131
+ <!-- Props and attributes -->
132
+ ![Image]{.rounded width="400"}
133
+
134
+ <!-- Slots and nesting -->
135
+ ::alert{type="warning"}
136
+ This is a warning message!
137
+ ::
138
+ ```
139
+
140
+ **Perfect for:**
141
+
142
+ - Nuxt Content projects
143
+ - Component-driven documentation
144
+ - Interactive markdown content
145
+ - Vue.js documentation sites
146
+
147
+ **File Usage:**
148
+
149
+ - `.mdc` extension - Dedicated MDC files (like `.mdx` for JSX)
150
+ - MDC syntax also works in `.md` and `.mdx` files
151
+
108
152
  ### MDD Support
109
153
 
110
154
  This formatter can **optionally** format `.mdd` files if you install the [MDD package](https://www.npmjs.com/package/@entro314labs/mdd):
@@ -127,10 +171,74 @@ pnpm run format
127
171
  markdownfix format [files...] # Format and fix markdown files
128
172
  markdownfix check [files...] # Check without writing changes
129
173
  markdownfix lint [files...] # Lint for issues only
174
+ markdownfix nuclear [files...] # 🚀 Run ALL linters and fixers
130
175
  markdownfix init # Create .remarkrc.js config
131
176
  markdownfix setup # Create example content structure
132
177
  ```
133
178
 
179
+ ### 🚀 Nuclear Mode
180
+
181
+ The `nuclear` command runs a comprehensive 4-step workflow that applies **all** available linters and fixers:
182
+
183
+ 1. **Remark Formatting** - Auto-fix markdown syntax
184
+ 2. **Remark Linting** - Validate markdown rules (40+ rules)
185
+ 3. **ESLint Auto-fix** - Fix JavaScript/JSX in code blocks
186
+ 4. **ESLint Linting** - Validate code quality
187
+
188
+ **Perfect for:**
189
+
190
+ - Pre-commit hooks
191
+ - CI/CD pipelines
192
+ - Major cleanup sessions
193
+ - Ensuring everything is pristine
194
+
195
+ **Usage:**
196
+
197
+ ```bash
198
+ # Run on all markdown files
199
+ markdownfix nuclear
200
+
201
+ # Run on specific directory
202
+ markdownfix nuclear --glob "docs/**/*.{md,mdx}"
203
+
204
+ # Add to package.json
205
+ {
206
+ "scripts": {
207
+ "precommit": "markdownfix nuclear"
208
+ }
209
+ }
210
+ ```
211
+
212
+ **Example Output:**
213
+
214
+ ```
215
+ 🚀 NUCLEAR MODE ACTIVATED
216
+
217
+ Processing 15 file(s) with comprehensive workflow...
218
+
219
+ Step 1/4: Running remark formatting...
220
+ ✓ Remark formatting completed
221
+
222
+ Step 2/4: Running remark linting...
223
+ ✓ Remark linting passed
224
+
225
+ Step 3/4: Running ESLint auto-fix...
226
+ ✓ ESLint auto-fix completed
227
+
228
+ Step 4/4: Running ESLint linting...
229
+ ✓ ESLint linting passed
230
+
231
+ ════════════════════════════════════════════════════════════
232
+ NUCLEAR MODE SUMMARY
233
+ ════════════════════════════════════════════════════════════
234
+ ✓ Remark Format PASS Formatted 15/15 files
235
+ ✓ Remark Lint PASS Linted 15 files
236
+ ✓ ESLint Fix PASS Auto-fixed code blocks
237
+ ✓ ESLint Lint PASS All code blocks valid
238
+ ════════════════════════════════════════════════════════════
239
+ 🎉 All checks passed! Your markdown is pristine.
240
+ ```
241
+
134
242
  ### Command Aliases
135
243
 
136
244
  The CLI is available via two commands:
@@ -182,11 +290,15 @@ pnpm run format # Apply fixes using remark-cli
182
290
  pnpm run format:check # Preview changes
183
291
 
184
292
  # Linting
185
- pnpm run lint # Check compliance
293
+ pnpm run lint # Remark-lint only
294
+ pnpm run lint:eslint # ESLint + MDX only
295
+ pnpm run lint:eslint:fix # ESLint auto-fix
296
+ pnpm run lint:all # Both remark and ESLint
186
297
 
187
298
  # Combined
188
- pnpm run process # Format then lint
189
- pnpm run process:safe # Dry-run first, then process
299
+ pnpm run process # Format then lint all
300
+ pnpm run process:safe # Dry-run first, then lint all
301
+ pnpm run nuclear # 🚀 Run ALL linters and fixers
190
302
  pnpm test # Same as process:safe
191
303
 
192
304
  # Utilities
@@ -227,6 +339,34 @@ Central configuration defining:
227
339
  4. Lint presets + rules
228
340
  5. `remark-stringify` - Must be last
229
341
 
342
+ ### `eslint.config.js` (Optional)
343
+
344
+ When using ESLint integration for MDX/code blocks:
345
+
346
+ **Global Installation Behavior:**
347
+
348
+ - ✅ Uses your local `eslint.config.js` if it exists
349
+ - ✅ Falls back to bundled config if not found
350
+ - ℹ️ Shows message: "Using bundled ESLint config"
351
+
352
+ **Custom Configuration:**
353
+
354
+ Create `eslint.config.js` in your project to override defaults:
355
+
356
+ ```javascript
357
+ import * as mdxPlugin from 'eslint-plugin-mdx';
358
+
359
+ export default [
360
+ {
361
+ files: ['**/*.{md,mdx,mdc,mdd}'],
362
+ ...mdxPlugin.flat,
363
+ // Your custom rules here
364
+ }
365
+ ];
366
+ ```
367
+
368
+ See [ESLINT\_INTEGRATION.md](ESLINT_INTEGRATION.md) for full details.
369
+
230
370
  ### `.remarkignore`
231
371
 
232
372
  Files excluded from processing:
@@ -358,6 +498,7 @@ Desktop knowledge management application with MDD integration:
358
498
  ## Documentation
359
499
 
360
500
  - **[content/guides/style-guide.md](content/guides/style-guide.md)** - Style specifications
501
+ - **[ESLINT\_INTEGRATION.md](ESLINT_INTEGRATION.md)** - ESLint + MDX integration guide
361
502
 
362
503
  ## Tech Stack
363
504
 
@@ -365,6 +506,8 @@ Desktop knowledge management application with MDD integration:
365
506
  - **Unified** - AST transformation
366
507
  - **GFM** - GitHub Flavored Markdown
367
508
  - **MDX** - JSX in markdown
509
+ - **MDC** - Markdown Components (Nuxt Content)
510
+ - **ESLint** - JavaScript/JSX linting in code blocks
368
511
 
369
512
  ## Contributing
370
513
 
package/cli.js CHANGED
@@ -17,8 +17,9 @@ import remarkStringify from 'remark-stringify';
17
17
  import fs from 'fs/promises';
18
18
  import path from 'path';
19
19
  import { glob } from 'glob';
20
+ import { execSync } from 'child_process';
20
21
 
21
- const MARKDOWN_EXTENSIONS = ['md', 'mdx', 'mdd'];
22
+ const MARKDOWN_EXTENSIONS = ['md', 'mdx', 'mdc', 'mdd'];
22
23
 
23
24
  // Import configuration from .remarkrc.js
24
25
  let remarkConfig;
@@ -44,6 +45,7 @@ COMMANDS:
44
45
  format [files] Format markdown files (writes changes)
45
46
  check [files] Check formatting without writing changes
46
47
  lint [files] Lint markdown files (no formatting)
48
+ nuclear [files] 🚀 Run ALL linters and fixers (remark + ESLint)
47
49
  init Create .remarkrc.js configuration file
48
50
  setup Create example content structure
49
51
 
@@ -52,6 +54,7 @@ OPTIONS:
52
54
  --version, -v Show version number
53
55
  --quiet, -q Suppress output except errors
54
56
  --glob <pattern> Use glob pattern (e.g., "**/*.md")
57
+ --nuclear Run complete lint+fix workflow (alias for nuclear command)
55
58
 
56
59
  EXAMPLES:
57
60
  # Format all markdown files in current directory
@@ -66,9 +69,22 @@ EXAMPLES:
66
69
  # Format quietly
67
70
  markdownfix format --quiet
68
71
 
72
+ # 🚀 Nuclear option - fix EVERYTHING
73
+ markdownfix nuclear
74
+ markdownfix format --nuclear
75
+
69
76
  # Initialize configuration
70
77
  markdownfix init
71
78
 
79
+ NUCLEAR MODE:
80
+ The nuclear command runs a comprehensive fix workflow:
81
+ 1. Remark formatting (auto-fix markdown syntax)
82
+ 2. Remark linting (validate markdown rules)
83
+ 3. ESLint auto-fix (fix JavaScript in code blocks)
84
+ 4. ESLint linting (validate code quality)
85
+
86
+ Perfect for: CI/CD, pre-commit hooks, major cleanups
87
+
72
88
  For more information, visit: https://github.com/entro314-labs/markdownfix
73
89
  `);
74
90
  }
@@ -168,6 +184,169 @@ async function processFiles(files, options = {}) {
168
184
  return { hasErrors, processedCount, totalFiles: files.length };
169
185
  }
170
186
 
187
+ /**
188
+ * Run nuclear mode - comprehensive fix workflow
189
+ * Executes: remark format -> remark lint -> eslint fix -> eslint lint
190
+ */
191
+ async function runNuclearMode(files, options = {}) {
192
+ const { quiet = false } = options;
193
+ const hasEslint = await checkEslintAvailable();
194
+
195
+ if (!quiet) {
196
+ console.log('\n🚀 NUCLEAR MODE ACTIVATED\n');
197
+ console.log(`Processing ${files.length} file(s) with comprehensive workflow...\n`);
198
+ }
199
+
200
+ let overallSuccess = true;
201
+ const steps = [];
202
+
203
+ // Step 1: Remark formatting
204
+ if (!quiet) console.log('Step 1/4: Running remark formatting...');
205
+ try {
206
+ const result = await processFiles(files, { write: true, quiet: true });
207
+ steps.push({
208
+ name: 'Remark Format',
209
+ success: !result.hasErrors,
210
+ details: `Formatted ${result.processedCount}/${result.totalFiles} files`
211
+ });
212
+ if (result.hasErrors) overallSuccess = false;
213
+ if (!quiet) console.log(` ✓ Remark formatting completed\n`);
214
+ } catch (error) {
215
+ steps.push({ name: 'Remark Format', success: false, details: error.message });
216
+ overallSuccess = false;
217
+ if (!quiet) console.log(` ✗ Remark formatting failed: ${error.message}\n`);
218
+ }
219
+
220
+ // Step 2: Remark linting
221
+ if (!quiet) console.log('Step 2/4: Running remark linting...');
222
+ try {
223
+ const result = await processFiles(files, { lintOnly: true, quiet: true });
224
+ steps.push({
225
+ name: 'Remark Lint',
226
+ success: !result.hasErrors,
227
+ details: `Linted ${result.totalFiles} files`
228
+ });
229
+ if (result.hasErrors) {
230
+ if (!quiet) console.log(' ⚠️ Remark linting found issues (check output above)\n');
231
+ overallSuccess = false;
232
+ } else {
233
+ if (!quiet) console.log(` ✓ Remark linting passed\n`);
234
+ }
235
+ } catch (error) {
236
+ steps.push({ name: 'Remark Lint', success: false, details: error.message });
237
+ overallSuccess = false;
238
+ if (!quiet) console.log(` ✗ Remark linting failed: ${error.message}\n`);
239
+ }
240
+
241
+ // Step 3 & 4: ESLint (only if available)
242
+ if (hasEslint) {
243
+ const eslintConfig = await getEslintConfigPath();
244
+ const configSource = eslintConfig.includes(process.cwd()) ? 'local' : 'bundled';
245
+
246
+ if (!quiet && configSource === 'bundled') {
247
+ console.log(' ℹ️ Using bundled ESLint config (no local config found)\n');
248
+ }
249
+
250
+ // Step 3: ESLint auto-fix
251
+ if (!quiet) console.log('Step 3/4: Running ESLint auto-fix...');
252
+ try {
253
+ const fileList = files.join(' ');
254
+ const eslintCmd = `npx eslint --config "${eslintConfig}" --fix ${fileList}`;
255
+
256
+ try {
257
+ execSync(eslintCmd, {
258
+ stdio: quiet ? 'pipe' : 'inherit',
259
+ cwd: process.cwd()
260
+ });
261
+ steps.push({ name: 'ESLint Fix', success: true, details: 'Auto-fixed code blocks' });
262
+ if (!quiet) console.log(` ✓ ESLint auto-fix completed\n`);
263
+ } catch (eslintError) {
264
+ // ESLint returns non-zero even if it fixes issues
265
+ steps.push({ name: 'ESLint Fix', success: false, details: 'Some issues could not be auto-fixed' });
266
+ if (!quiet) console.log(` ⚠️ ESLint auto-fix completed with warnings\n`);
267
+ }
268
+ } catch (error) {
269
+ steps.push({ name: 'ESLint Fix', success: false, details: error.message });
270
+ if (!quiet) console.log(` ✗ ESLint auto-fix failed: ${error.message}\n`);
271
+ }
272
+
273
+ // Step 4: ESLint linting
274
+ if (!quiet) console.log('Step 4/4: Running ESLint linting...');
275
+ try {
276
+ const fileList = files.join(' ');
277
+ const eslintCmd = `npx eslint --config "${eslintConfig}" ${fileList}`;
278
+
279
+ execSync(eslintCmd, {
280
+ stdio: quiet ? 'pipe' : 'inherit',
281
+ cwd: process.cwd()
282
+ });
283
+ steps.push({ name: 'ESLint Lint', success: true, details: 'All code blocks valid' });
284
+ if (!quiet) console.log(` ✓ ESLint linting passed\n`);
285
+ } catch (eslintError) {
286
+ steps.push({ name: 'ESLint Lint', success: false, details: 'Linting issues found' });
287
+ overallSuccess = false;
288
+ if (!quiet) console.log(` ⚠️ ESLint linting found issues\n`);
289
+ }
290
+ } else {
291
+ if (!quiet) {
292
+ console.log('Step 3/4: Skipping ESLint (not installed)');
293
+ console.log(' ℹ️ Install ESLint with: npm install -D eslint eslint-plugin-mdx\n');
294
+ console.log('Step 4/4: Skipping ESLint linting\n');
295
+ }
296
+ steps.push({ name: 'ESLint Fix', success: true, details: 'Skipped (not installed)' });
297
+ steps.push({ name: 'ESLint Lint', success: true, details: 'Skipped (not installed)' });
298
+ }
299
+
300
+ // Summary
301
+ if (!quiet) {
302
+ console.log('═'.repeat(60));
303
+ console.log('NUCLEAR MODE SUMMARY');
304
+ console.log('═'.repeat(60));
305
+ steps.forEach(step => {
306
+ const icon = step.success ? '✓' : '✗';
307
+ const status = step.success ? 'PASS' : 'FAIL';
308
+ console.log(`${icon} ${step.name.padEnd(20)} ${status.padEnd(6)} ${step.details}`);
309
+ });
310
+ console.log('═'.repeat(60));
311
+ if (overallSuccess) {
312
+ console.log('🎉 All checks passed! Your markdown is pristine.\n');
313
+ } else {
314
+ console.log('⚠️ Some issues remain. Review the output above.\n');
315
+ }
316
+ }
317
+
318
+ return { success: overallSuccess, steps };
319
+ }
320
+
321
+ /**
322
+ * Check if ESLint is available in the project
323
+ */
324
+ async function checkEslintAvailable() {
325
+ try {
326
+ execSync('npx eslint --version', { stdio: 'pipe' });
327
+ return true;
328
+ } catch {
329
+ return false;
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Get ESLint config path
335
+ * Returns the config from current directory if it exists, otherwise uses the bundled one
336
+ */
337
+ async function getEslintConfigPath() {
338
+ const localConfig = path.join(process.cwd(), 'eslint.config.js');
339
+
340
+ try {
341
+ await fs.access(localConfig);
342
+ return localConfig;
343
+ } catch {
344
+ // Use bundled config from markdownfix package
345
+ const bundledConfig = new URL('./eslint.config.js', import.meta.url).pathname;
346
+ return bundledConfig;
347
+ }
348
+ }
349
+
171
350
  /**
172
351
  * Initialize .remarkrc.js configuration
173
352
  */
@@ -250,6 +429,7 @@ async function main() {
250
429
  // Parse options
251
430
  const options = {
252
431
  quiet: commandArgs.includes('--quiet') || commandArgs.includes('-q'),
432
+ nuclear: commandArgs.includes('--nuclear'),
253
433
  glob: null
254
434
  };
255
435
 
@@ -274,6 +454,14 @@ async function main() {
274
454
  console.log('No markdown files found');
275
455
  return;
276
456
  }
457
+
458
+ // Check for --nuclear flag
459
+ if (options.nuclear) {
460
+ const result = await runNuclearMode(files, { quiet: options.quiet });
461
+ process.exit(result.success ? 0 : 1);
462
+ break;
463
+ }
464
+
277
465
  if (!options.quiet) {
278
466
  console.log(`Formatting ${files.length} file(s)...`);
279
467
  }
@@ -331,6 +519,17 @@ async function main() {
331
519
  break;
332
520
  }
333
521
 
522
+ case 'nuclear': {
523
+ const files = await getFiles(fileArgs, options.glob);
524
+ if (files.length === 0) {
525
+ console.log('No markdown files found');
526
+ return;
527
+ }
528
+ const result = await runNuclearMode(files, { quiet: options.quiet });
529
+ process.exit(result.success ? 0 : 1);
530
+ break;
531
+ }
532
+
334
533
  default:
335
534
  console.error(`Unknown command: ${command}`);
336
535
  console.error('Run "markdownfix --help" for usage information');
@@ -0,0 +1,82 @@
1
+ /**
2
+ * ESLint configuration for MDX files
3
+ * Uses eslint-plugin-mdx with existing remark-lint configuration
4
+ *
5
+ * This integrates with the existing .remarkrc.js file to provide:
6
+ * - JSX/JavaScript linting inside MDX code blocks
7
+ * - IDE integration for better developer experience
8
+ * - Unified linting workflow alongside remark-lint
9
+ */
10
+
11
+ import * as mdxPlugin from 'eslint-plugin-mdx';
12
+
13
+ export default [
14
+ {
15
+ // Ignore common directories
16
+ // Replaces .eslintignore file (no longer supported in ESLint 9)
17
+ ignores: [
18
+ 'node_modules/**',
19
+ 'dist/**',
20
+ 'build/**',
21
+ '.next/**',
22
+ 'coverage/**',
23
+ 'pnpm-lock.yaml',
24
+ '**/*.config.js',
25
+ '**/*.config.mjs',
26
+ 'README.md',
27
+ 'CHANGELOG.md',
28
+ 'LICENSE',
29
+ 'PUBLISHING.md',
30
+ 'ESLINT_INTEGRATION.md',
31
+ '.cache/**',
32
+ '.remark-cache/**'
33
+ ]
34
+ },
35
+
36
+ // MDX/MDC files configuration
37
+ {
38
+ name: 'custom/mdx/recommended',
39
+ files: ['**/*.{md,mdx,mdc,mdd}'],
40
+ ...mdxPlugin.flat,
41
+ processor: mdxPlugin.createRemarkProcessor({
42
+ lintCodeBlocks: true, // Enable linting of code blocks
43
+ languageMapper: {} // Use default language mappings
44
+ }),
45
+ rules: {
46
+ // MDX-specific rules from eslint-plugin-mdx
47
+ // The remark-lint rules from .remarkrc.js will be automatically used
48
+ 'mdx/remark': 'error',
49
+ },
50
+ settings: {
51
+ 'mdx/code-blocks': true, // Enable code block linting
52
+ 'mdx/language-mapper': {} // Use default mappings
53
+ }
54
+ },
55
+
56
+ // Code blocks in MDX/MDC (optional - for stricter linting)
57
+ {
58
+ name: 'custom/mdx/code-blocks',
59
+ files: ['**/*.{md,mdx,mdc,mdd}'],
60
+ ...mdxPlugin.flatCodeBlocks,
61
+ languageOptions: {
62
+ globals: {
63
+ console: 'readonly',
64
+ process: 'readonly',
65
+ require: 'readonly',
66
+ module: 'readonly',
67
+ exports: 'readonly',
68
+ __dirname: 'readonly',
69
+ __filename: 'readonly',
70
+ }
71
+ },
72
+ rules: {
73
+ ...mdxPlugin.flatCodeBlocks.rules,
74
+ // Add JavaScript rules for code blocks
75
+ 'no-var': 'error',
76
+ 'prefer-const': 'error',
77
+ 'no-unused-vars': 'warn',
78
+ // Allow common globals in documentation examples
79
+ 'no-undef': 'off',
80
+ }
81
+ }
82
+ ];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@entro314labs/markdownfix",
3
- "version": "0.0.7",
4
- "description": "Opinionated markdown formatter and linter for MD, MDD and MDX files using Remark/Unified ecosystem",
3
+ "version": "0.0.11",
4
+ "description": "Opinionated markdown formatter and linter for MD, MDX, MDC, and MDD files using Remark/Unified ecosystem",
5
5
  "type": "module",
6
6
  "repository": {
7
7
  "type": "git",
@@ -14,9 +14,11 @@
14
14
  "files": [
15
15
  ".remarkrc.js",
16
16
  ".remarkignore",
17
+ "eslint.config.js",
17
18
  "setup.js",
18
19
  "cli.js",
19
20
  "README.md",
21
+ "ESLINT_INTEGRATION.md",
20
22
  "LICENSE"
21
23
  ],
22
24
  "bin": {
@@ -27,6 +29,7 @@
27
29
  "keywords": [
28
30
  "markdown",
29
31
  "mdx",
32
+ "mdc",
30
33
  "mdd",
31
34
  "linter",
32
35
  "formatter",
@@ -35,11 +38,16 @@
35
38
  "unified",
36
39
  "markdownfix",
37
40
  "markdown-linter",
41
+ "markdown-components",
42
+ "nuxt-content",
38
43
  "opinionated"
39
44
  ],
40
45
  "author": "Dominikos Pritis",
41
46
  "license": "MIT",
42
47
  "devDependencies": {
48
+ "eslint": "^9.38.0",
49
+ "eslint-plugin-mdx": "^3.6.2",
50
+ "eslint-plugin-react": "^7.37.5",
43
51
  "markdown-link-check": "^3.14.1",
44
52
  "remark-cli": "^12.0.1"
45
53
  },
@@ -49,7 +57,7 @@
49
57
  "dependencies": {
50
58
  "@adobe/remark-gridtables": "^3.0.15",
51
59
  "@code-dot-org/remark-plugins": "^2.0.0",
52
- "@entro314labs/mdd": "^0.0.7",
60
+ "@entro314labs/remark-mdd": "^0.0.10",
53
61
  "@theguild/remark-mermaid": "^0.3.0",
54
62
  "fumadocs-docgen": "^3.0.2",
55
63
  "glob": "^11.0.3",
@@ -118,11 +126,15 @@
118
126
  },
119
127
  "scripts": {
120
128
  "lint": "remark . --quiet --frail",
129
+ "lint:eslint": "eslint --config eslint.config.js .",
130
+ "lint:eslint:fix": "eslint --config eslint.config.js --fix .",
131
+ "lint:all": "pnpm run lint && pnpm run lint:eslint",
121
132
  "format": "remark . --output --quiet",
122
133
  "format:check": "remark . --quiet",
123
- "check-links": "markdown-link-check **/*.{md,mdx,mdd}",
124
- "process": "pnpm run format && pnpm run lint",
125
- "process:safe": "pnpm run format:check && pnpm run lint",
134
+ "check-links": "markdown-link-check **/*.{md,mdx,mdc,mdd}",
135
+ "process": "pnpm run format && pnpm run lint:all",
136
+ "process:safe": "pnpm run format:check && pnpm run lint:all",
137
+ "nuclear": "node cli.js nuclear",
126
138
  "clean-cache": "rm -rf .remark-cache",
127
139
  "test": "pnpm run process:safe"
128
140
  }