Skip to content

Commit 0740b09

Browse files
committed
docs category
1 parent 104ac01 commit 0740b09

7 files changed

Lines changed: 517 additions & 167 deletions

File tree

.github/workflows/deploy-mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
paths-ignore:
88
- 'README.md'
99
- 'docs/all-articles.md'
10+
- 'docs/all-categories.md'
1011
workflow_dispatch:
1112

1213
permissions:

.github/workflows/update-readme.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
paths-ignore:
88
- 'README.md'
99
- 'docs/all-articles.md'
10+
- 'docs/all-categories.md'
1011
- 'mkdocs.yml'
1112
workflow_dispatch:
1213

@@ -37,7 +38,7 @@ jobs:
3738
- name: Check if files changed
3839
id: check_changes
3940
run: |
40-
if git diff --quiet README.md docs/all-articles.md mkdocs.yml; then
41+
if git diff --quiet README.md docs/all-articles.md docs/all-categories.md mkdocs.yml; then
4142
echo "changed=false" >> $GITHUB_OUTPUT
4243
else
4344
echo "changed=true" >> $GITHUB_OUTPUT
@@ -48,6 +49,6 @@ jobs:
4849
run: |
4950
git config --local user.email "action@github.com"
5051
git config --local user.name "GitHub Action"
51-
git add README.md docs/all-articles.md mkdocs.yml
52-
git commit -m "docs: auto-update README, all-articles and mkdocs nav"
52+
git add README.md docs/all-articles.md docs/all-categories.md mkdocs.yml
53+
git commit -m "docs: auto-update README, all-articles, all-categories and mkdocs nav"
5354
git push

README.md

Lines changed: 45 additions & 44 deletions
Large diffs are not rendered by default.

docs/all-articles.md

Lines changed: 44 additions & 44 deletions
Large diffs are not rendered by default.

docs/all-categories.md

Lines changed: 272 additions & 0 deletions
Large diffs are not rendered by default.

mkdocs.yml

Lines changed: 62 additions & 61 deletions
Large diffs are not rendered by default.

scripts/generate_readme.py

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33
"""
4-
自动生成 README.md、docs/all-articles.md、mkdocs.yml nav
4+
自动生成 README.md、docs/all-articles.md、docs/all-categories.md、mkdocs.yml nav
55
66
用法:
77
python scripts/generate_readme.py # 同时生成 readme + all-articles
88
python scripts/generate_readme.py --target readme
99
python scripts/generate_readme.py --target all-articles
10+
python scripts/generate_readme.py --target all-categories
1011
python scripts/generate_readme.py --target mkdocs-nav
1112
python scripts/generate_readme.py --target both # readme + all-articles
12-
python scripts/generate_readme.py --target all # readme + all-articles + mkdocs-nav
13+
python scripts/generate_readme.py --target all # readme + all-articles + all-categories + mkdocs-nav
1314
"""
1415

1516
import argparse
@@ -28,6 +29,7 @@
2829
{'首页': 'index.md'},
2930
{'关于': 'about.md'},
3031
{'全部栏目': 'all-articles.md'},
32+
{'全部分类': 'all-categories.md'},
3133
{'MkDocs 博客方案': 'MkDocs博客方案.md'},
3234
{'标签': 'tags/index.md'},
3335
]
@@ -92,7 +94,7 @@ def parse_front_matter(filepath, content):
9294
# ──────────────────────────────────────────────
9395

9496
def get_article_info(filepath):
95-
"""返回 (title, date) 或 None(需跳过)"""
97+
"""返回文章信息 dict 或 None(需跳过)"""
9698
try:
9799
content = Path(filepath).read_text(encoding='utf-8')
98100
except Exception as e:
@@ -107,15 +109,25 @@ def get_article_info(filepath):
107109

108110
title = None
109111
date = None
112+
categories = []
110113

111114
if fm is not None:
112115
raw_title = fm.get('title')
113116
raw_date = fm.get('date')
117+
raw_categories = fm.get('categories')
118+
114119
if raw_title is not None:
115120
title = str(raw_title).strip()
116121
if raw_date is not None:
117122
date = str(raw_date).strip()
118123

124+
if isinstance(raw_categories, list):
125+
categories = [str(x).strip() for x in raw_categories if str(x).strip()]
126+
elif raw_categories is not None:
127+
c = str(raw_categories).strip()
128+
if c:
129+
categories = [c]
130+
119131
if not title:
120132
m = re.search(r'title:\s*["\']?([^"\'\n]+)["\']?', content)
121133
if m:
@@ -129,24 +141,29 @@ def get_article_info(filepath):
129141
if not date:
130142
date = datetime.fromtimestamp(os.path.getmtime(filepath)).strftime('%Y-%m-%d')
131143

132-
return title, date
144+
return {
145+
'title': title,
146+
'date': date,
147+
'categories': categories,
148+
}
133149

134150

135151
# ──────────────────────────────────────────────
136152
# 扫描 docs/
137153
# ──────────────────────────────────────────────
138154

139155
def scan_docs():
140-
"""返回 (articles, skipped_files, dir_order)"""
156+
"""返回 (articles, category_articles, skipped_files, dir_order)"""
141157
docs_dir = Path('docs').resolve()
142158
repo_root = docs_dir.parent
143159
articles = defaultdict(list)
160+
category_articles = defaultdict(list)
144161
skipped_files = []
145162
dir_order = [] # 保留扫描到的目录名顺序
146163

147164
if not docs_dir.exists():
148165
print(f'error: {docs_dir} does not exist')
149-
return articles, skipped_files, dir_order
166+
return articles, category_articles, skipped_files, dir_order
150167

151168
for category_dir in sorted(docs_dir.iterdir()):
152169
if not category_dir.is_dir() or category_dir.name.startswith('.'):
@@ -161,15 +178,26 @@ def scan_docs():
161178
if info is None:
162179
skipped_files.append(str(md_file.relative_to(repo_root)).replace('\\', '/'))
163180
continue
164-
title, date = info
181+
182+
title = info['title']
183+
date = info['date']
184+
fm_categories = info['categories']
185+
165186
readme_path = str(md_file.relative_to(repo_root)).replace('\\', '/')
166187
docs_path = str(md_file.relative_to(docs_dir)).replace('\\', '/')
167-
articles[category_name].append((title, date, readme_path, docs_path, dir_name))
188+
189+
entry = (title, date, readme_path, docs_path, dir_name)
190+
articles[category_name].append(entry)
168191
has_article = True
192+
193+
article_categories = fm_categories if fm_categories else ['未分类']
194+
for c in article_categories:
195+
category_articles[c].append(entry)
196+
169197
if has_article or (category_dir / 'index.md').exists():
170198
dir_order.append(dir_name)
171199

172-
return articles, skipped_files, dir_order
200+
return articles, category_articles, skipped_files, dir_order
173201

174202

175203
# ──────────────────────────────────────────────
@@ -199,10 +227,16 @@ def update_readme(new_section):
199227
end_marker = '## \U0001f3d7\ufe0f 仓库定位'
200228
start_idx = content.find(start_marker)
201229
end_idx = content.find(end_marker)
202-
if start_idx == -1 or end_idx == -1:
230+
if start_idx == -1:
203231
print('error: cannot find article index section in README.md')
204232
return False
205-
readme_path.write_text(content[:start_idx] + new_section + '\n\n' + content[end_idx:], encoding='utf-8')
233+
234+
if end_idx == -1 or end_idx < start_idx:
235+
# 如果 README 里没有后续“仓库定位”分节,则替换到文件末尾
236+
readme_path.write_text(content[:start_idx] + new_section + '\n', encoding='utf-8')
237+
else:
238+
readme_path.write_text(content[:start_idx] + new_section + '\n\n' + content[end_idx:], encoding='utf-8')
239+
206240
print('README.md updated')
207241
return True
208242

@@ -240,6 +274,37 @@ def create_all_articles_page(content):
240274
return True
241275

242276

277+
def generate_all_categories_page(category_articles):
278+
lines = [
279+
'---',
280+
'title: "全部分类"',
281+
'date: "2026-03-25"',
282+
'comments: false',
283+
'---',
284+
'',
285+
'# 全部分类',
286+
'',
287+
'这里列出博客中的全部文章,按文章 front matter 中定义的 `categories` 分组。',
288+
'',
289+
]
290+
291+
for category in sorted(category_articles.keys()):
292+
items = category_articles[category]
293+
sorted_items = sorted(items, key=lambda x: x[1], reverse=True)
294+
lines.append(f'## {category}{len(sorted_items)}\n')
295+
for title, date, readme_path, docs_path, dir_name in sorted_items:
296+
lines.append('- **' + date + '** - [' + title + '](' + docs_path + ')')
297+
lines.append('')
298+
299+
return '\n'.join(lines)
300+
301+
302+
def create_all_categories_page(content):
303+
Path('docs/all-categories.md').write_text(content, encoding='utf-8')
304+
print('docs/all-categories.md updated')
305+
return True
306+
307+
243308
# ──────────────────────────────────────────────
244309
# mkdocs.yml nav
245310
# ──────────────────────────────────────────────
@@ -307,20 +372,20 @@ def main():
307372
parser = argparse.ArgumentParser()
308373
parser.add_argument(
309374
'--target',
310-
choices=['readme', 'all-articles', 'mkdocs-nav', 'both', 'all'],
375+
choices=['readme', 'all-articles', 'all-categories', 'mkdocs-nav', 'both', 'all'],
311376
default='both',
312-
help='选择要生成的目标(both=readme+all-articles,all=readme+all-articles+mkdocs-nav)',
377+
help='选择要生成的目标(both=readme+all-articles,all=readme+all-articles+all-categories+mkdocs-nav)',
313378
)
314379
args = parser.parse_args()
315380

316381
print('scanning docs/...')
317-
articles, skipped_files, dir_order = scan_docs()
382+
articles, category_articles, skipped_files, dir_order = scan_docs()
318383

319384
if not articles:
320385
print('warning: no articles found')
321386
else:
322387
total = sum(len(items) for items in articles.values())
323-
print(f'found {total} articles in {len(articles)} categories')
388+
print(f'found {total} articles in {len(articles)} directory categories and {len(category_articles)} front-matter categories')
324389

325390
if skipped_files:
326391
print(f'warning: skipped {len(skipped_files)} file(s) due to invalid front matter')
@@ -329,6 +394,7 @@ def main():
329394

330395
do_readme = args.target in ('readme', 'both', 'all')
331396
do_all_articles = args.target in ('all-articles', 'both', 'all')
397+
do_all_categories = args.target in ('all-categories', 'all')
332398
do_nav = args.target in ('mkdocs-nav', 'all')
333399

334400
if do_readme:
@@ -347,6 +413,14 @@ def main():
347413
print('error: failed to write docs/all-articles.md')
348414
raise SystemExit(1)
349415

416+
if do_all_categories:
417+
print('generating all-categories page...')
418+
all_categories_content = generate_all_categories_page(category_articles)
419+
print('writing docs/all-categories.md...')
420+
if not create_all_categories_page(all_categories_content):
421+
print('error: failed to write docs/all-categories.md')
422+
raise SystemExit(1)
423+
350424
if do_nav:
351425
print('generating mkdocs.yml nav...')
352426
nav = generate_mkdocs_nav(articles, dir_order)

0 commit comments

Comments
 (0)