curiositech/mdx-sanitizer
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.
npx skills add https://github.com/curiositech/some_claude_skills --skill mdx-sanitizer
Comprehensive MDX content sanitizer that prevents JSX parsing errors caused by angle brackets, generics, and other conflicting patterns.
MDX 2.x treats unescaped < and { as JSX syntax. This causes build failures when content contains:
Promise<T>, Array<string>, Map<K, V><100ms, <=, >=-->, <--, -><link> in prose, <tag> placeholders<>This skill implements a three-layer defense:
Content is sanitized when syncing from .claude/skills/ to website/docs/:
syncSkillDocs.ts - Main skill filessyncSkillSubpages.ts - Reference filesdoc-generator.ts - Generated docsThe git pre-commit hook validates files before commit using validate-brackets.js.
npm run validate:all runs as part of prebuild to catch any issues.
cd website
npm run sanitize:mdx
# or with verbose output
npm run sanitize:mdx -- --verbose
cd website
npm run sanitize:mdx -- --fix
# or shorthand
npm run fix:mdx
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
}
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.
website/scripts/lib/mdx-sanitizer.ts - Core sanitizer modulewebsite/scripts/sanitize-mdx.ts - CLI wrapperwebsite/scripts/syncSkillDocs.ts - Integrationwebsite/scripts/syncSkillSubpages.ts - Integrationwebsite/scripts/lib/doc-generator.ts - Integrationwebsite/package.json - npm scripts<100, <0.5ms<=, >=<><--, -->Promise<T>, Array<string>< value<link>, <tag> (not valid HTML)npm run clearnpm run sanitize:mdx -- --fixnpm run buildIf valid JSX components are being escaped:
<MyComponent>)For edge cases, manually escape in source:
<T> < and >Take curiositech/mdx-sanitizer from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.