11import os
22import 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