AI 批量重新生成所有菜谱描述,规范化图片alt文本

- 363 个菜谱全部重新生成描述(30-300字,覆盖特点/营养/难度/时长)
- 134 张图片 alt 规范化:菜名-预览图-N 格式
- 新增 lint 规则:描述质量检查、图片 alt 文本规范
- 修复所有手动 lint / textlint / markdownlint 错误

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Anduin Xue
2026-05-23 10:20:23 +00:00
parent 8031e5b0d4
commit 539a2b7a9a
364 changed files with 620 additions and 552 deletions

View File

@@ -182,6 +182,58 @@ const validators = [
}
},
// 检查菜谱描述30-300字需包含特点、营养价值、难度、制作时长
async (filePath, lines, errors) => {
if (filePath.includes('template/示例菜')) return;
const titles = lines.filter(l => l.startsWith('#'));
const mainTitleIndex = titles.length > 0 ? lines.indexOf(titles[0]) : -1;
const sections = lines.filter(l => l.startsWith('## '));
const firstSecondTitleIndex = sections.length > 0 ? lines.indexOf(sections[0]) : -1;
if (mainTitleIndex < 0 || firstSecondTitleIndex < 0) return;
const contentBetweenTitles = lines.slice(mainTitleIndex + 1, firstSecondTitleIndex);
const descriptionLines = contentBetweenTitles.filter(line => {
if (line === '') return false;
if (/^!\[.*\]\(.*\)$/.test(line)) return false;
if (/^预估烹饪难度:/.test(line)) return false;
if (/^预估卡路里:/.test(line)) return false;
return true;
});
const description = descriptionLines.join('').trim();
if (description.length === 0) {
errors.push(`文件 ${filePath} 不符合仓库的规范!缺少菜谱描述。请在主标题和"预估烹饪难度"之间添加一段30-300字的菜谱介绍包含菜品特点、营养价值、难度和制作时长。`);
} else if (description.length < 30) {
errors.push(`文件 ${filePath} 不符合仓库的规范!菜谱描述太短(当前 ${description.length} 字),至少需要 30 字。请补充菜品特点、营养价值、难度和制作时长。`);
} else if (description.length > 300) {
errors.push(`文件 ${filePath} 不符合仓库的规范!菜谱描述太长(当前 ${description.length} 字),最多 300 字。请精简描述。`);
}
},
// 检查图片 alt 文本质量
async (filePath, lines, errors) => {
if (filePath.includes('template/示例菜')) return;
const content = lines.join('\n');
const altRegex = /!\[([^\]]*)\]\([^)]+\.(?:jpg|jpeg|png|gif|webp|svg)\)/gi;
let match;
while ((match = altRegex.exec(content)) !== null) {
const alt = match[1];
const prefix = alt.slice(0, 20);
if (alt === '示例菜成品') {
errors.push(`文件 ${filePath} 不符合仓库的规范!图片 alt 文本不能为"示例菜成品",请替换为实际菜名!`);
} else if (/^[a-zA-Z0-9_-]+$/.test(alt) && alt.length < 20) {
errors.push(`文件 ${filePath} 不符合仓库的规范!图片 alt 文本"${alt}"看起来是拼音或英文缩写,应使用中文菜名!`);
} else if (alt === '成品' || alt === '效果图' || alt === '摆盘') {
errors.push(`文件 ${filePath} 不符合仓库的规范!图片 alt 文本"${alt}"过于泛泛,应包含具体菜名!`);
}
}
},
// 检查图片引用是否存在
async (filePath, lines, errors) => {
const fileDir = path.dirname(filePath);