mdx-validator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

MDX Validator

MDX Validator

MDX 语法预检查工具,补充现有工具(eslint-mdx, prettier)。
MDX语法预检查工具,补充现有工具(eslint-mdx、prettier)的能力。

🎯 设计理念

🎯 设计理念

与现有工具的关系

与现有工具的关系

eslint-mdx (基础 MDX 检查)
    +
prettier (格式化)
    +
mdx-validator (Fumadocs 专项检查) ← 你在这里
完整的 MDX 质量保证
为什么需要本 skill:
  • eslint-mdx 不检查图片文件名规范
  • prettier 不检查翻译完整性
  • 现有工具没有 Fumadocs 特定问题的检查
eslint-mdx (基础 MDX 检查)
    +
prettier (格式化)
    +
mdx-validator (Fumadocs 专项检查) ← 你在这里
完整的 MDX 质量保证
为什么需要本Skill:
  • eslint-mdx 不检查图片文件名规范
  • prettier 不检查翻译完整性
  • 现有工具没有针对Fumadocs特定问题的检查

📦 前置条件

📦 前置条件

推荐安装(可选)

推荐安装(可选)

bash
undefined
bash
undefined

1. 安装 eslint-mdx(官方 MDX 检查工具)

1. 安装 eslint-mdx(官方 MDX 检查工具)

npm install -D eslint-plugin-mdx
npm install -D eslint-plugin-mdx

2. 安装 prettier(MDX 格式化)

2. 安装 prettier(MDX 格式化)

npm install -D prettier
npm install -D prettier

3. 创建配置

3. 创建配置

echo '{"extends":["plugin:mdx/recommended"]}' > .eslintrc.json
undefined
echo '{"extends":["plugin:mdx/recommended"]}' > .eslintrc.json
undefined

🔍 检查项

🔍 检查项

Step 0: 使用现有工具(如果有)

Step 0: 使用现有工具(如果有)

bash
undefined
bash
undefined

检查是否有 eslint-mdx

检查是否有 eslint-mdx

if [ -f "node_modules/eslint-plugin-mdx" ]; then echo "✅ 发现 eslint-mdx,运行检查..." npx eslint "**/*.mdx" --fix else echo "⚠️ 未安装 eslint-mdx,跳过基础检查" echo " 推荐: npm install -D eslint-plugin-mdx" fi
if [ -f "node_modules/eslint-plugin-mdx" ]; then echo "✅ 发现 eslint-mdx,运行检查..." npx eslint "**/*.mdx" --fix else echo "⚠️ 未安装 eslint-mdx,跳过基础检查" echo " 推荐: npm install -D eslint-plugin-mdx" fi

检查是否有 prettier

检查是否有 prettier

if [ -f "node_modules/prettier" ]; then echo "✅ 发现 prettier,格式化..." npx prettier --write "**/*.mdx" fi
undefined
if [ -f "node_modules/prettier" ]; then echo "✅ 发现 prettier,格式化..." npx prettier --write "**/*.mdx" fi
undefined

Step 1: 特殊字符检查(MDX 语法)

Step 1: 特殊字符检查(MDX 语法)

问题字符:
  • <
    - 被解析为 JSX 标签
  • >
    - 被解析为 JSX 标签
  • {
    }
    - 被解析为 JSX 表达式
检查命令:
bash
undefined
问题字符:
  • <
    - 会被解析为JSX标签
  • >
    - 会被解析为JSX标签
  • {
    }
    - 会被解析为JSX表达式
检查命令:
bash
undefined

检查危险的 < 符号(不在代码块和 HTML 标签中)

检查危险的 < 符号(不在代码块和 HTML 标签中)

grep -n '<[^a-zA-Z/!]' .mdx | grep -v '```' | grep -v '^.:.*<(a|img|div|span|p|h[1-6]|ul|ol|li|code|pre|strong|em|br|hr)'
grep -n '<[^a-zA-Z/!]' .mdx | grep -v '```' | grep -v '^.:.*<(a|img|div|span|p|h[1-6]|ul|ol|li|code|pre|strong|em|br|hr)'

检查危险的 > 符号(不在代码块中)

检查危险的 > 符号(不在代码块中)

grep -n '>[^a-zA-Z/]' .mdx | grep -v '```' | grep -v '^.:.*</(a|img|div|span|p|h[1-6|ul|ol|li|code|pre|strong|em)>'
undefined
grep -n '>[^a-zA-Z/]' .mdx | grep -v '```' | grep -v '^.:.*</(a|img|div|span|p|h[1-6|ul|ol|li|code|pre|strong|em)>'
undefined

2. 图片路径检查

2. 图片路径检查

问题模式:
img-1.png
,
screenshot-10.png
检查命令:
bash
undefined
问题模式:
img-1.png
,
screenshot-10.png
检查命令:
bash
undefined

检查连字符+数字的文件名

检查连字符+数字的文件名

grep -nE '(img|image|screenshot|fig|figure)-[0-9]+.(png|jpg|webp|gif)' *.mdx
undefined
grep -nE '(img|image|screenshot|fig|figure)-[0-9]+.(png|jpg|webp|gif)' *.mdx
undefined

3. Frontmatter 检查

3. Frontmatter 检查

必需字段:
title
,
description
检查命令:
bash
undefined
必需字段:
title
,
description
检查命令:
bash
undefined

检查缺失 title 的文件

检查缺失 title 的文件

grep -L '^title:' *.mdx
grep -L '^title:' *.mdx

检查缺失 description 的文件

检查缺失 description 的文件

grep -L '^description:' *.mdx
grep -L '^description:' *.mdx

检查 description 长度(建议 50-160 字符)

检查 description 长度(建议 50-160 字符)

for f in *.mdx; do desc=$(grep '^description:' "$f" | cut -d':' -f2-) len=${#desc} if [ $len -lt 50 ] || [ $len -gt 160 ]; then echo "⚠️ $f: description 长度 $len(建议 50-160)" fi done
undefined
for f in *.mdx; do desc=$(grep '^description:' "$f" | cut -d':' -f2-) len=${#desc} if [ $len -lt 50 ] || [ $len -gt 160 ]; then echo "⚠️ $f: description 长度 $len(建议 50-160)" fi done
undefined

4. 代码块完整性检查

4. 代码块完整性检查

检查命令:
bash
undefined
检查命令:
bash
undefined

检查未闭合的代码块

检查未闭合的代码块

awk '/^```/{flag=1-flag} END{if(flag)print "❌ 未闭合的代码块"}' *.mdx
awk '/^```/{flag=1-flag} END{if(flag)print "❌ 未闭合的代码块"}' *.mdx

检查代码块语言标识

检查代码块语言标识

grep -n '^```[^a-z]$' .mdx | grep -v '^.:.````*$'
undefined
grep -n '^```[^a-z]$' .mdx | grep -v '^.:.````*$'
undefined

5. 翻译完整性检查

5. 翻译完整性检查

改进后的检测逻辑:
bash
undefined
改进后的检测逻辑:
bash
undefined

1. 定义常见的英文技术术语(不应被检测为未翻译)

1. 定义常见的英文技术术语(不应被检测为未翻译)

TECH_TERMS=( "React|TypeScript|JavaScript|Node.js|npm|yarn|pnpm" "API|SDK|CLI|GUI|IDE|JSON|YAML|XML|HTTP|HTTPS" "CSS|HTML|SQL|NoSQL|REST|GraphQL" "Git|GitHub|GitLab|Bitbucket" "Docker|Kubernetes|AWS|GCP|Azure" "MacOS|Windows|Linux|Ubuntu|Debian" "CDN|DNS|SSL|TLS|OAuth|JWT" )
TECH_TERMS=( "React|TypeScript|JavaScript|Node.js|npm|yarn|pnpm" "API|SDK|CLI|GUI|IDE|JSON|YAML|XML|HTTP|HTTPS" "CSS|HTML|SQL|NoSQL|REST|GraphQL" "Git|GitHub|GitLab|Bitbucket" "Docker|Kubernetes|AWS|GCP|Azure" "MacOS|Windows|Linux|Ubuntu|Debian" "CDN|DNS|SSL|TLS|OAuth|JWT" )

合并为正则表达式

合并为正则表达式

TECH_REGEX=$(IFS="|"; echo "${TECH_TERMS[*]}")
TECH_REGEX=$(IFS="|"; echo "${TECH_TERMS[*]}")

2. 检查中文文件中的英文单词(排除技术术语)

2. 检查中文文件中的英文单词(排除技术术语)

for f in content/docs/zh-CN/*.mdx; do

统计英文单词数量(排除技术术语)

english=$(grep -oE '\b[A-Za-z]+\b' "$f" |
grep -v -E "^($TECH_REGEX)$" |
wc -l)

统计总词数

total=$(wc -w < "$f")

计算英文占比

if [ $total -gt 0 ]; then ratio=$((english * 100 / total)) if [ $ratio -gt 20 ]; then echo "⚠️ $f: 英文占比 ${ratio}%,可能未翻译" fi fi done
for f in content/docs/zh-CN/*.mdx; do

统计英文单词数量(排除技术术语)

english=$(grep -oE '\b[A-Za-z]+\b' "$f" |
grep -v -E "^($TECH_REGEX)$" |
wc -l)

统计总词数

total=$(wc -w < "$f")

计算英文占比

if [ $total -gt 0 ]; then ratio=$((english * 100 / total)) if [ $ratio -gt 20 ]; then echo "⚠️ $f: 英文占比 ${ratio}%,可能未翻译" fi fi done

3. 检查正文内容是否与英文版相同(排除 frontmatter)

3. 检查正文内容是否与英文版相同(排除 frontmatter)

for f in content/docs/zh-CN/*.mdx; do en_file="${f/zh-CN/en}" if [ -f "$en_file" ]; then # 提取正文(跳过前 10 行 frontmatter) zh_body=$(tail -n +10 "$f") en_body=$(tail -n +10 "$en_file")
if [ "$zh_body" = "$en_body" ]; then
  echo "❌ $f: 正文内容与英文版相同,未翻译!"
fi
fi done
for f in content/docs/zh-CN/*.mdx; do en_file="${f/zh-CN/en}" if [ -f "$en_file" ]; then # 提取正文(跳过前 10 行 frontmatter) zh_body=$(tail -n +10 "$f") en_body=$(tail -n +10 "$en_file")
if [ "$zh_body" = "$en_body" ]; then
  echo "❌ $f: 正文内容与英文版相同,未翻译!"
fi
fi done

4. 智能检测(基于句子级别)

4. 智能检测(基于句子级别)

for f in content/docs/zh-CN/*.mdx; do

提取包含大量英文的句子

grep -nE '^[^#][A-Za-z]{20,}[^#]$' "$f" |
grep -v '```' |
grep -v '<!--' |
head -5 done

**更智能的检测**:

```bash
for f in content/docs/zh-CN/*.mdx; do

提取包含大量英文的句子

grep -nE '^[^#][A-Za-z]{20,}[^#]$' "$f" |
grep -v '```' |
grep -v '<!--' |
head -5 done

**更智能的检测**:

```bash

使用 MDX AST 解析(更准确)

使用 MDX AST 解析(更准确)

需要安装: npm install -D remark remark-mdx

需要安装: npm install -D remark remark-mdx

npx remark content/docs/zh-CN/article.mdx
--use remark-mdx
--tree |
jq '.. | .value? | select(. != null) | select(test("[A-Za-z]{10,}"))'
undefined
npx remark content/docs/zh-CN/article.mdx
--use remark-mdx
--tree |
jq '.. | .value? | select(. != null) | select(test("[A-Za-z]{10,}"))'
undefined

自动修复

自动修复

优先使用 prettier

优先使用 prettier

bash
undefined
bash
undefined

如果有 prettier,优先使用

如果有 prettier,优先使用

if command -v prettier &> /dev/null; then echo "✅ 使用 prettier 格式化..." prettier --write "**/*.mdx" fi
undefined
if command -v prettier &> /dev/null; then echo "✅ 使用 prettier 格式化..." prettier --write "**/*.mdx" fi
undefined

修复特殊字符

修复特殊字符

bash
undefined
bash
undefined

修复 < 符号(数字前)

修复 < 符号(数字前)

sed -i 's|<([0-9])|under \1|g' *.mdx sed -i 's|<([0-9])|<\1|g' *.mdx # 或使用 HTML 实体
sed -i 's|<([0-9])|under \1|g' *.mdx sed -i 's|<([0-9])|<\1|g' *.mdx # 或使用 HTML 实体

修复 > 符号(数字前)

修复 > 符号(数字前)

sed -i 's|>([0-9])|over \1|g' *.mdx sed -i 's|>([0-9])|>\1|g' *.mdx # 或使用 HTML 实体
undefined
sed -i 's|>([0-9])|over \1|g' *.mdx sed -i 's|>([0-9])|>\1|g' *.mdx # 或使用 HTML 实体
undefined

修复图片路径

修复图片路径

bash
undefined
bash
undefined

修复连字符+数字的文件名

修复连字符+数字的文件名

img-1.png → img01.png

img-1.png → img01.png

screenshot-10.png → screenshot10.png

screenshot-10.png → screenshot10.png

sed -i -E 's|(img|image|screenshot|fig|figure)-([0-9]+).|\1\2.|g' *.mdx
undefined
sed -i -E 's|(img|image|screenshot|fig|figure)-([0-9]+).|\1\2.|g' *.mdx
undefined

修复 Frontmatter

修复 Frontmatter

bash
undefined
bash
undefined

添加缺失的 title(如果文件名有意义)

添加缺失的 title(如果文件名有意义)

for f in *.mdx; do if ! grep -q '^title:' "$f"; then title=$(basename "$f" .mdx | sed 's/-/ /g' | sed 's/\b(.)/\u\1/') sed -i "1i---\ntitle: $title\n---" "$f" fi done
undefined
for f in *.mdx; do if ! grep -q '^title:' "$f"; then title=$(basename "$f" .mdx | sed 's/-/ /g' | sed 's/\b(.)/\u\1/') sed -i "1i---\ntitle: $title\n---" "$f" fi done
undefined

使用方式

使用方式

方式 1: 完整检查(推荐)

方式 1: 完整检查(推荐)

bash
undefined
bash
undefined

1. 基础检查(如果有 eslint-mdx)

1. 基础检查(如果有 eslint-mdx)

if [ -f "node_modules/eslint-plugin-mdx" ]; then npx eslint "**/*.mdx" --fix fi
if [ -f "node_modules/eslint-plugin-mdx" ]; then npx eslint "**/*.mdx" --fix fi

2. 格式化(如果有 prettier)

2. 格式化(如果有 prettier)

if [ -f "node_modules/prettier" ]; then npx prettier --write "**/*.mdx" fi
if [ -f "node_modules/prettier" ]; then npx prettier --write "**/*.mdx" fi

3. Fumadocs 专项检查

3. Fumadocs 专项检查

mdx-validator --check-images --check-translation
mdx-validator --check-images --check-translation

4. 自动修复剩余问题

4. 自动修复剩余问题

mdx-validator --fix
undefined
mdx-validator --fix
undefined

方式 2: 仅使用 mdx-validator

方式 2: 仅使用 mdx-validator

bash
undefined
bash
undefined

检查单个文件

检查单个文件

mdx-validator article.mdx
mdx-validator article.mdx

检查目录下所有文件

检查目录下所有文件

mdx-validator content/docs/en/**/*.mdx
mdx-validator content/docs/en/**/*.mdx

检查并修复

检查并修复

mdx-validator --fix content/docs/en/**/*.mdx
undefined
mdx-validator --fix content/docs/en/**/*.mdx
undefined

方式 2: 集成到工作流

方式 3: 集成到工作流

bash
undefined
bash
undefined

在翻译后运行

在翻译后运行

article-translator article.mdx --to zh mdx-validator --fix content/docs/zh/article.mdx
article-translator article.mdx --to zh mdx-validator --fix content/docs/zh/article.mdx

在构建前运行

在构建前运行

mdx-validator content/docs/**/*.mdx && pnpm build:docs
undefined
mdx-validator content/docs/**/*.mdx && pnpm build:docs
undefined

输出示例

输出示例

=== MDX Validation Report ===

File: content/docs/en/ai-ml/jina-vlm.mdx

✅ Special characters: OK
⚠️  Image paths: 2 issues found
  Line 45: img-10.png → img10.png
  Line 78: screenshot-1.png → screenshot01.png
✅ Frontmatter: OK
✅ Code blocks: OK

Auto-fix available: mdx-validator --fix jina-vlm.mdx
=== MDX Validation Report ===

File: content/docs/en/ai-ml/jina-vlm.mdx

✅ Special characters: OK
⚠️  Image paths: 2 issues found
  Line 45: img-10.png → img10.png
  Line 78: screenshot-1.png → screenshot01.png
✅ Frontmatter: OK
✅ Code blocks: OK

Auto-fix available: mdx-validator --fix jina-vlm.mdx

配置

配置

可在项目根目录创建
.mdx-validator.json
:
json
{
  "rules": {
    "specialChars": true,
    "imagePaths": true,
    "frontmatter": true,
    "codeBlocks": true
  },
  "autoFix": false,
  "ignore": ["node_modules", ".next"]
}
可在项目根目录创建
.mdx-validator.json
:
json
{
  "rules": {
    "specialChars": true,
    "imagePaths": true,
    "frontmatter": true,
    "codeBlocks": true
  },
  "autoFix": false,
  "ignore": ["node_modules", ".next"]
}

与其他 Skills 配合

与其他 Skills 配合

fumadocs-article-importer (导入文章)
article-translator (翻译内容)
┌────────┴────────┐
│  eslint-mdx     │ ← 基础 MDX 检查(推荐)
│  prettier       │ ← 格式化(推荐)
└────────┬────────┘
mdx-validator ← 你在这里(Fumadocs 专项检查)
pnpm build:docs (构建)
fumadocs-deploy (部署验证)
fumadocs-article-importer (导入文章)
article-translator (翻译内容)
┌────────┴────────┐
│  eslint-mdx     │ ← 基础 MDX 检查(推荐)
│  prettier       │ ← 格式化(推荐)
└────────┬────────┘
mdx-validator ← 你在这里(Fumadocs 专项检查)
pnpm build:docs (构建)
fumadocs-deploy (部署验证)

🆚 与现有工具对比

🆚 与现有工具对比

检查项eslint-mdxprettiermdx-validator
MDX JSX 语法--
Markdown 语法--
代码风格--
特殊字符(MDX)--
图片文件名--
翻译完整性--
Fumadocs 特定--
结论:
  • 使用 eslint-mdx + prettier 进行基础检查
  • 使用 mdx-validator 进行专项检查
  • 三者互补,不冲突
检查项eslint-mdxprettiermdx-validator
MDX JSX 语法--
Markdown 语法--
代码风格--
特殊字符(MDX)--
图片文件名--
翻译完整性--
Fumadocs 特定--
结论:
  • 使用eslint-mdx + prettier进行基础检查
  • 使用mdx-validator进行专项检查
  • 三者互补,不存在冲突

常见问题

常见问题

Q: 为什么要预检查?

Q: 为什么要进行预检查?

A: MDX 语法错误在构建时才会发现,预检查可以:
  • 提前发现问题,节省构建时间
  • 自动修复常见问题
  • 避免 CI/CD 失败
A: MDX语法错误通常在构建阶段才会被发现,预检查可以:
  • 提前发现问题,节省构建时间
  • 自动修复常见问题
  • 避免CI/CD流程失败

Q: 哪些字符是安全的?

Q: 哪些字符是安全的?

A:
  • 安全: 字母、数字、基本标点(
    . , ! ? ; : ' " ( )
  • 不安全:
    <
    >
    {
    }
    &
    (需要特殊处理)
  • 代码块中: 所有字符都安全
A:
  • 安全字符: 字母、数字、基础标点(
    . , ! ? ; : ' " ( )
  • 不安全字符:
    <
    >
    {
    }
    &
    (需要特殊处理)
  • 代码块内: 所有字符均安全

Q: 图片路径为什么不能用连字符?

Q: 图片路径为什么不能使用连字符?

A: MDX 会将
img-1.png
解析为
img
减去
1.png
,导致路径错误。 使用
img01.png
openclaw01.png
可避免此问题。
A: MDX会将
img-1.png
解析为
img
减去
1.png
,导致路径解析错误。使用
img01.png
openclaw01.png
这类命名方式可避免该问题。