https://github.com/anduin2017/howtocook
程序员在家做饭方法指南。Programmer's guide about how to cook at home (Simplified Chinese only).
https://github.com/anduin2017/howtocook
chinese cookbook cooking dishes recipes
Last synced: 22 days ago
JSON representation
程序员在家做饭方法指南。Programmer's guide about how to cook at home (Simplified Chinese only).
- Host: GitHub
- URL: https://github.com/anduin2017/howtocook
- Owner: Anduin2017
- License: unlicense
- Created: 2020-02-29T10:43:49.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2025-09-12T04:07:40.000Z (26 days ago)
- Last Synced: 2025-09-12T06:20:35.148Z (26 days ago)
- Topics: chinese, cookbook, cooking, dishes, recipes
- Language: Dockerfile
- Homepage: https://cook.aiursoft.cn
- Size: 443 MB
- Stars: 93,166
- Watchers: 491
- Forks: 10,491
- Open Issues: 442
-
Metadata Files:
- Readme: .github/readme-generate.js
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
const { readdir, writeFile, stat } = require('fs/promises');
const fs = require('fs').promises;
const path = require('path');const README_PATH = './README.md';
const MKDOCS_PATH = 'mkdocs.yml';
const dishesFolder = 'dishes';
const starsystemFolder = 'starsystem';const ignorePaths = ['.git', 'README.md', 'node_modules', 'CONTRIBUTING.md', '.github'];
const categories = {
vegetable_dish: {
title: '素菜',
readme: '',
mkdocs: '',
},
meat_dish: {
title: '荤菜',
readme: '',
mkdocs: '',
},
aquatic: {
title: '水产',
readme: '',
mkdocs: '',
},
breakfast: {
title: '早餐',
readme: '',
mkdocs: '',
},
staple: {
title: '主食',
readme: '',
mkdocs: '',
},
'semi-finished': {
title: '半成品加工',
readme: '',
mkdocs: '',
},
soup: {
title: '汤与粥',
readme: '',
mkdocs: '',
},
drink: {
title: '饮料',
readme: '',
mkdocs: '',
},
condiment: {
title: '酱料和其它材料',
readme: '',
mkdocs: '',
},
dessert: {
title: '甜品',
readme: '',
mkdocs: '',
},
};async function countStars(filename) {
const data = await fs.readFile(filename, 'utf-8');
let stars = 0;
const lines = data.split('\n');
lines.forEach(line => {
stars += (line.match(/★/g) || []).length;
});
return stars;
}async function organizeByStars(dishesFolder, starsystemFolder) {
const dishes = {};async function processFolder(folderPath) {
const files = await readdir(folderPath);
for (const filename of files) {
const filepath = path.join(folderPath, filename);
const fileStat = await stat(filepath);
if (fileStat.isFile() && filename.endsWith('.md')) {
const stars = await countStars(filepath);
dishes[filepath] = stars;
} else if (fileStat.isDirectory()) {
await processFolder(filepath);
}
}
}const dishesFolderAbs = path.resolve(dishesFolder);
const starsystemFolderAbs = path.resolve(starsystemFolder);if (!await fs.access(starsystemFolderAbs).then(() => true).catch(() => false)) {
await fs.mkdir(starsystemFolderAbs, { recursive: true });
}if (!await fs.access(dishesFolderAbs).then(() => true).catch(() => false)) {
console.log(`Directory not found: ${dishesFolderAbs}, creating directory...`);
await fs.mkdir(dishesFolderAbs, { recursive: true });
}await processFolder(dishesFolderAbs);
const starRatings = Array.from(new Set(Object.values(dishes))).sort((a, b) => a - b);
const navigationLinks = [];for (const stars of starRatings) {
const starsFile = path.join(starsystemFolderAbs, `${stars}Star.md`);
const content = [`# ${stars} 星难度菜品`, ''];
for (const [filepath, starCount] of Object.entries(dishes)) {
if (starCount === stars) {
const relativePath = path.relative(starsystemFolderAbs, filepath).replace(/\\/g, '/');
content.push(`* [${path.basename(filepath, '.md')}](./${relativePath})`);
}
}
await writeFile(starsFile, content.join('\n'), 'utf-8');
navigationLinks.push(`- [${stars} 星难度](${path.relative(path.dirname(README_PATH), starsFile).replace(/\\/g, '/')})`);
}return navigationLinks;
}async function main() {
try {
let README_BEFORE = '', README_MAIN = '', README_AFTER = '';
let MKDOCS_BEFORE = '', MKDOCS_MAIN = '', MKDOCS_AFTER = '';
const markdownObj = await getAllMarkdown('.');
// Debug logging to understand the structure of markdownObj
console.log("Markdown Object Structure:", JSON.stringify(markdownObj, null, 2));
for (const markdown of markdownObj) {
console.log("Processing markdown:", markdown);
if (markdown.path.includes('tips/advanced')) {
README_AFTER += inlineReadmeTemplate(markdown.file, markdown.path);
MKDOCS_AFTER += inlineMkdocsTemplate(markdown.file, markdown.path);
continue;
}if (markdown.path.includes('tips')) {
README_BEFORE += inlineReadmeTemplate(markdown.file, markdown.path);
MKDOCS_BEFORE += inlineMkdocsTemplate(markdown.file, markdown.path);
continue;
}for (const category of Object.keys(categories)) {
if (!markdown.path.includes(category)) continue;
categories[category].readme += inlineReadmeTemplate(markdown.file, markdown.path);
categories[category].mkdocs += inlineMkdocsTemplate(
markdown.file,
markdown.path,
true,
);
}
}for (const category of Object.values(categories)) {
README_MAIN += categoryReadmeTemplate(category.title, category.readme);
MKDOCS_MAIN += categoryMkdocsTemplate(category.title, category.mkdocs);
}let MKDOCS_TEMPLATE;
let README_TEMPLATE;try {
MKDOCS_TEMPLATE = await fs.readFile("./.github/templates/mkdocs_template.yml", "utf-8");
} catch (error) {
MKDOCS_TEMPLATE = `site_name: My Docs\nnav:\n {{main}}\n`;
console.warn("mkdocs_template.yml not found, using default template");
}try {
README_TEMPLATE = await fs.readFile("./.github/templates/readme_template.md", "utf-8");
} catch (error) {
README_TEMPLATE = `# My Project\n\n{{before}}\n\n{{main}}\n\n{{after}}`;
console.warn("readme_template.md not found, using default template");
}const navigationLinks = await organizeByStars(dishesFolder, starsystemFolder);
// Debug logging to ensure navigationLinks is defined and contains data
console.log("难度索引", navigationLinks);
const navigationSection = `\n### 按难度索引\n\n${navigationLinks.join('\n')}`;await writeFile(
README_PATH,
README_TEMPLATE
.replace('{{before}}', README_BEFORE.trim())
.replace('{{index_stars}}', navigationSection.trim())
.replace('{{main}}', README_MAIN.trim())
.replace('{{after}}', README_AFTER.trim()),
);await writeFile(
MKDOCS_PATH,
MKDOCS_TEMPLATE
.replace('{{before}}', MKDOCS_BEFORE)
.replace('{{main}}', MKDOCS_MAIN)
.replace('{{after}}', MKDOCS_AFTER),
);// Organize files by star rating
//await organizeByStars(dishesFolder, starsystemFolder);
} catch (error) {
console.error(error);
}
}async function getAllMarkdown(dir) {
const paths = [];
const files = await readdir(dir);
files.sort((a, b) => a.localeCompare(b, 'zh-CN'));for (const file of files) {
const filePath = path.join(dir, file);
if (ignorePaths.includes(file)) continue;
const fileStat = await stat(filePath);
if (fileStat.isFile() && file.endsWith('.md')) {
paths.push({ path: dir, file });
} else if (fileStat.isDirectory()) {
const subFiles = await getAllMarkdown(filePath);
paths.push(...subFiles);
}
}
return paths;
}function inlineReadmeTemplate(file, path) {
return `- [${file.replace('.md', '')}](${path}/${file})\n`;
}function categoryReadmeTemplate(title, inlineStr) {
return `\n### ${title}\n\n${inlineStr}`;
}function inlineMkdocsTemplate(file, path, isDish = false) {
return `${' '.repeat(isDish ? 10 : 6)}- ${file.replace('.md', '')}: ${path}/${file}\n`;
}function categoryMkdocsTemplate(title, inlineStr) {
return `\n${' '.repeat(6)}- ${title}:\n${inlineStr}`;
}main();