Skip to content

Commit 2e03439

Browse files
committed
跟进最新设计
1 parent 5f45c4e commit 2e03439

26 files changed

+390
-549
lines changed

auto_sidebar.py

Lines changed: 195 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,204 @@
11
import os
22
import re
3-
import json
4-
import csv
53

6-
# 从Markdown内容中提取第一个H1标题
7-
def extract_title(md_content):
8-
match = re.search(r'^#\s+(.*)', md_content, re.MULTILINE)
9-
if match:
10-
return match.group(1)
11-
return None
4+
def escape_quotes(text: str) -> str:
5+
"""
6+
转义字符串中的双引号
7+
8+
Args:
9+
text: 需要转义的文本
10+
11+
Returns:
12+
转义后的文本
13+
"""
14+
return text.replace('"', '\\"')
1215

13-
# 生成侧边栏结构
14-
def generate_sidebar_structure(base_path, title: dict, language='zh'):
15-
# 初始化侧边栏结构
16-
path = f"/{language}/quickstart/"
17-
sidebar = { f"{path}" : []}
18-
# 遍历指定目录下的所有文件
19-
for root, dirs, files in os.walk(base_path):
20-
for file in files:
21-
if file.endswith(".md"): # 筛选Markdown文件
22-
file_path = os.path.join(root, file)
23-
with open(file_path, 'r', encoding='utf-8') as md_file:
24-
content = md_file.read()
25-
title = extract_title(content) # 提取标题
26-
if title:
27-
# 生成相对路径链接
28-
relative_path = os.path.relpath(file_path, base_path).replace('\\', '/')
29-
link = f"{path}{relative_path[:-3]}" # 移除.md扩展名
30-
# 获取分类名称
31-
category = os.path.basename(os.path.dirname(file_path))[2:]
32-
# 查找或创建分类条目
33-
if not title_dict.keys().__contains__(category):
34-
continue
35-
category_entry = next((item for item in sidebar[path] if item["text"] == title_dict[category]), None)
36-
if not category_entry:
37-
category_entry = {"text": title_dict[category], "items": []}
38-
sidebar[path].append(category_entry)
39-
# 添加链接到分类条目
40-
category_entry["items"].append({"text": title, "link": link})
41-
return sidebar
16+
def remove_or_replace_badge_tags(text: str) -> str:
17+
"""
18+
移除或替换标题中的 <Badge> 标签
19+
20+
Args:
21+
text: 包含 Badge 标签的文本
22+
23+
Returns:
24+
处理后的文本
25+
"""
26+
# 移除所有的 <Badge> 标签,并在末尾添加一个 *
27+
# 使用正则表达式匹配 <Badge> 标签
28+
badge_pattern = r'<Badge[^>]*>[^<]*</Badge>'
29+
if re.search(badge_pattern, text):
30+
# 移除所有 Badge 标签
31+
cleaned_text = re.sub(badge_pattern, '', text)
32+
# 清理多余的空格
33+
cleaned_text = re.sub(r'\s+', ' ', cleaned_text).strip()
34+
# 添加星号标记
35+
return f"{cleaned_text}*"
36+
return text
4237

43-
# 将侧边栏结构写入TypeScript文件,键名不带引号
44-
def write_sidebar_ts(sidebar, output_file):
45-
def dict_to_ts(obj, indent=0):
46-
"""递归地将字典转换为TypeScript对象字面量字符串,特定键名不带引号"""
47-
ts_str = "{\n"
48-
indent_str = " " * (indent + 1)
49-
for k, v in obj.items():
50-
# 检查键名是否为特定的几个,如果是,则不使用json.dumps
51-
if k in ["text", "item", "link"]:
52-
key_str = k
53-
else:
54-
key_str = json.dumps(k, ensure_ascii=False)
38+
def generate_sidebar(base_path: str, lang: str) -> list:
39+
"""
40+
根据指定语言路径下的文件结构生成侧边栏配置
41+
42+
Args:
43+
base_path: 文档根路径
44+
lang: 语言代码 ('zh' 或 'en')
45+
46+
Returns:
47+
侧边栏配置列表
48+
"""
49+
sidebar_items = []
50+
quickstart_path = os.path.join(base_path, lang, 'quickstart')
51+
52+
# 按章节顺序处理文件夹
53+
if os.path.exists(quickstart_path):
54+
chapters = sorted(os.listdir(quickstart_path))
55+
56+
for chapter in chapters:
57+
chapter_path = os.path.join(quickstart_path, chapter)
58+
if os.path.isdir(chapter_path):
59+
# 提取章节信息
60+
chapter_info = extract_chapter_info(chapter_path, lang)
61+
if chapter_info:
62+
sidebar_items.append(chapter_info)
63+
64+
return sidebar_items
65+
66+
def extract_chapter_info(chapter_path: str, lang: str) -> dict:
67+
"""
68+
提取章节信息,包括章节标题和子项
69+
70+
Args:
71+
chapter_path: 章节路径
72+
lang: 语言代码
73+
74+
Returns:
75+
章节信息字典
76+
"""
77+
# 获取章节编号和名称
78+
chapter_name = os.path.basename(chapter_path)
79+
chapter_num = chapter_name.split('-')[0] if '-' in chapter_name else chapter_name
80+
81+
# 获取章节下的所有文件
82+
files = sorted([f for f in os.listdir(chapter_path)
83+
if f.endswith('.md') and not f.startswith('index')])
84+
85+
if not files:
86+
return None
87+
88+
# 获取章节标题(从第一个文件中提取)
89+
first_file = files[0]
90+
chapter_title = extract_title_from_file(os.path.join(chapter_path, first_file), lang)
91+
92+
# 处理 Badge 标签
93+
chapter_title = remove_or_replace_badge_tags(chapter_title)
94+
95+
# 构建子项
96+
items = []
97+
for file in files:
98+
file_path = os.path.join(chapter_path, file)
99+
title = extract_title_from_file(file_path, lang)
100+
link = f"/{lang}/quickstart/{chapter_name}/{file.replace('.md', '')}"
101+
102+
# 处理 Badge 标签
103+
title = remove_or_replace_badge_tags(title)
104+
105+
# 转义标题中的双引号
106+
title = escape_quotes(title)
107+
108+
items.append({"text": title, "link": link})
109+
110+
# 转义章节标题中的双引号
111+
chapter_title = escape_quotes(chapter_title)
112+
113+
return {
114+
"text": chapter_title,
115+
"items": items
116+
}
117+
118+
def extract_title_from_file(file_path: str, lang: str) -> str:
119+
"""
120+
从Markdown文件中提取标题
121+
122+
Args:
123+
file_path: 文件路径
124+
lang: 语言代码
125+
126+
Returns:
127+
提取的标题
128+
"""
129+
try:
130+
with open(file_path, 'r', encoding='utf-8') as f:
131+
content = f.read()
55132

56-
if isinstance(v, dict):
57-
v_str = dict_to_ts(v, indent + 1)
58-
elif isinstance(v, list):
59-
v_str = "[\n" + ",\n".join([indent_str + " " + dict_to_ts(item, indent + 2) for item in v]) + "\n" + indent_str + "]"
60-
else:
61-
v_str = json.dumps(v, ensure_ascii=False)
62-
ts_str += f"{indent_str}{key_str}: {v_str},\n"
63-
ts_str += " " * indent + "}"
64-
return ts_str
133+
# 查找第一个标题(以#开头的行)
134+
title_match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
135+
if title_match:
136+
return title_match.group(1).strip()
137+
except Exception:
138+
pass
139+
140+
# 如果无法提取标题,则使用文件名
141+
filename = os.path.basename(file_path).replace('.md', '')
142+
return filename
65143

66-
sidebar_ts_content = f"""import {{ DefaultTheme }} from 'vitepress';
144+
def generate_sidebar_ts(base_path: str, output_path: str):
145+
"""
146+
生成完整的sidebar.ts文件
147+
148+
Args:
149+
base_path: 文档根路径
150+
output_path: 输出文件路径
151+
"""
152+
# 生成中英文侧边栏
153+
zh_sidebar = generate_sidebar(base_path, 'zh')
154+
en_sidebar = generate_sidebar(base_path, 'en')
155+
156+
# 构建TypeScript代码
157+
ts_code = '''import { DefaultTheme } from 'vitepress';
67158
68-
export const sidebar: DefaultTheme.Sidebar = {dict_to_ts(sidebar, 0)};
69-
"""
70-
with open(output_file, 'w', encoding='utf-8') as ts_file:
71-
ts_file.write(sidebar_ts_content)
159+
export const sidebar: DefaultTheme.Sidebar = {
160+
"/zh/quickstart/": [
161+
'''
162+
163+
# 添加中文侧边栏
164+
for item in zh_sidebar:
165+
ts_code += ' {\n'
166+
ts_code += f' text: "{item["text"]}",\n'
167+
ts_code += ' "items": [\n'
168+
169+
for sub_item in item["items"]:
170+
ts_code += f' {{\n text: "{sub_item["text"]}",\n link: "{sub_item["link"]}",\n }},\n'
171+
172+
ts_code += ' ],\n'
173+
ts_code += ' },\n'
174+
175+
ts_code += ' ],\n'
176+
ts_code += ' "/en/quickstart/": [\n'
177+
178+
# 添加英文侧边栏
179+
for item in en_sidebar:
180+
ts_code += ' {\n'
181+
ts_code += f' text: "{item["text"]}",\n'
182+
ts_code += ' "items": [\n'
183+
184+
for sub_item in item["items"]:
185+
ts_code += f' {{\n text: "{sub_item["text"]}",\n link: "{sub_item["link"]}",\n }},\n'
186+
187+
ts_code += ' ],\n'
188+
ts_code += ' },\n'
189+
190+
ts_code += ' ],\n'
191+
ts_code += '};\n'
192+
193+
# 写入文件
194+
with open(output_path, 'w', encoding='utf-8') as f:
195+
f.write(ts_code)
72196

73-
# 指定Markdown文件所在目录和输出文件路径
74-
output_file = 'docs/.vitepress/sidebar.ts'
75-
# 读取csv文件获取标题。第一行为文件夹名,第二行是中文标题,第三行是英文标题
76-
with open('titles.csv', 'r', encoding='utf-8') as csvfile:
77-
reader = csv.reader(csvfile)
78-
title = [row for row in reader]
79-
csvfile.close()
80-
# 生成键值对
81-
title_dict = {}
82-
for i in range(len(title[0])):
83-
title_dict[title[0][i]] = title[1][i]
84-
# 生成侧边栏结构并写入文件
85-
sidebar = generate_sidebar_structure('docs/zh/quickstart', title_dict, 'zh')
86-
#英文
87-
for i in range(len(title[0])):
88-
title_dict[title[0][i]] = title[2][i]
89-
en_sidebar = generate_sidebar_structure('docs/en/quickstart', title_dict, 'en')
90-
#合并
91-
for key in en_sidebar:
92-
sidebar[key] = en_sidebar[key]
93-
write_sidebar_ts(sidebar, output_file)
197+
# 使用示例
198+
if __name__ == "__main__":
199+
# 设置文档根目录路径
200+
docs_path = "docs" # 根据实际情况调整路径
201+
202+
# 生成sidebar.ts
203+
generate_sidebar_ts(docs_path, "docs/.vitepress/sidebar.ts")
204+
print("sidebar.ts 文件已生成")

0 commit comments

Comments
 (0)