--- name: mdx-sanitizer description: Sanitize MDX content for Docusaurus builds. Fixes unescaped angle brackets (<, >, <=, >=), Liquid/Nunjucks template syntax ({{ }}), TypeScript generics (Promise<T>), and inline code backtick edge cases. Use when pre-commit hooks fail on bracket or Liquid validation, or when MDX/JSX build errors reference unexpected tokens. NOT for general markdown linting or prose editing. allowed-tools: - Read - Write - Edit - Bash - Glob - Grep version: 1.0.0 triggers: - mdx error - angle bracket - jsx parsing - build failure mdx - escape angle brackets - sanitize markdown metadata: category: DevOps & Automation tags: - mdx - docusaurus - markdown - build-tools - sanitization pairs-with: - skill: site-reliability-engineer reason: MDX build failures are a primary Docusaurus deployment blocker that SRE validates - skill: technical-writer reason: Technical writers produce the MDX content that needs sanitization for safe rendering - skill: skill-documentarian reason: Skill documentation in MDX format requires sanitization before website deployment --- # MDX Sanitizer Comprehensive MDX content sanitizer that prevents JSX parsing errors caused by angle brackets, generics, and other conflicting patterns. ## The Problem MDX 2.x treats unescaped `<` and `{` as JSX syntax. This causes build failures when content contains: - **TypeScript generics**: `Promise<T>`, `Array<string>`, `Map<K, V>` - **Comparisons**: `<100ms`, `<=`, `>=` - **Arrows**: `-->`, `<--`, `->` - **Invalid tags**: `<link>` in prose, `<tag>` placeholders - **Empty brackets**: `<>` ## Solution Architecture This skill implements a three-layer defense: ### 1. Sync-Time Sanitization (Proactive) Content is sanitized when syncing from `.claude/skills/` to `website/docs/`: - `syncSkillDocs.ts` - Main skill files - `syncSkillSubpages.ts` - Reference files - `doc-generator.ts` - Generated docs ### 2. Pre-Commit Validation (Reactive) The git pre-commit hook validates files before commit using `validate-brackets.js`. ### 3. Build-Time Validation (Final Check) `npm run validate:all` runs as part of `prebuild` to catch any issues. ## Usage ### Check for Issues (Dry Run) ```bash cd website npm run sanitize:mdx # or with verbose output npm run sanitize:mdx -- --verbose ``` ### Fix All Issues ```bash cd website npm run sanitize:mdx -- --fix # or shorthand npm run fix:mdx ``` ### Programmatic API ```typescript import { sanitizeForMdx, validateMdxSafety, isMdxSafe } from './lib/mdx-sanitizer'; // Sanitize content const result = sanitizeForMdx(content, { useHtmlEntities: true }); if (result.modified) { console.log(`Fixed ${result.issues.length} issues`); fs.writeFileSync(path, result.content); } // Validate without modifying const issues = validateMdxSafety(content, 'path/to/file.md'); // Quick check if (!isMdxSafe(content)) { // Handle issues } ``` ## Escaping Strategies The sanitizer uses HTML entities for maximum compatibility: | Pattern | Original | Escaped | |---------|----------|---------| | Less-than | `<` | `<` | | Greater-than | `>` | `>` | | Generics | `<T>` | `&lt;T&gt;` | | Comparison | `<=` | `&lt;=` | Content inside code blocks (`` ``` `` or `` ` ``) is automatically protected and never escaped. ## Files Modified - `website/scripts/lib/mdx-sanitizer.ts` - Core sanitizer module - `website/scripts/sanitize-mdx.ts` - CLI wrapper - `website/scripts/syncSkillDocs.ts` - Integration - `website/scripts/syncSkillSubpages.ts` - Integration - `website/scripts/lib/doc-generator.ts` - Integration - `website/package.json` - npm scripts ## Patterns Detected 1. **Less-than before digit**: `<100`, `<0.5ms` 2. **Comparison operators**: `<=`, `>=` 3. **Empty brackets**: `<>` 4. **Arrows**: `<--`, `-->` 5. **Generic types**: `Promise<T>`, `Array<string>` 6. **Space after less-than**: `< value` 7. **Invalid pseudo-tags**: `<link>`, `<tag>` (not valid HTML) ## Troubleshooting ### Build Still Fails After Running Sanitizer 1. Clear Docusaurus cache: `npm run clear` 2. Re-run sanitizer: `npm run sanitize:mdx -- --fix` 3. Rebuild: `npm run build` ### False Positives If valid JSX components are being escaped: - Ensure they use PascalCase (e.g., `<MyComponent>`) - Check they're valid HTML5 elements ### Manual Escaping For edge cases, manually escape in source: - Use backticks for inline code: `` `<T>` `` - Use fenced code blocks for multi-line - Use HTML entities: `<` and `>` ## Sources - [MDX Troubleshooting](https://mdxjs.com/docs/troubleshooting-mdx/) - [TypeDoc MDX Issues](https://github.com/tgreyuk/typedoc-plugin-markdown/issues/167)