Skip to content

Commit 48c102e

Browse files
committed
feat: Implement configurable independent community sub-sites with modular navigation base on verl
docs: add myst_parser dependency and FAQ section to documentation - Add myst_parser to environment dependencies - Implement FAQ module in the documentation pages
1 parent ea5a335 commit 48c102e

23 files changed

Lines changed: 28252 additions & 14 deletions

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ fetch-config:
3939
# Initialize submodules if not exists (use pinned commits for reproducibility)
4040
_repos/verl _repos/VeOmni _repos/LLaMA-Factory _repos/ms-swift:
4141
@echo "Initializing submodules..."
42-
@git submodule update --init
42+
@git submodule sync --recursive
43+
@git submodule update --init --remote
4344

4445
# Copy documentation from submodules
4546
copy-docs: _repos/verl _repos/VeOmni _repos/LLaMA-Factory _repos/ms-swift

_static/ascend_config.json

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

_static/custom.css

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,34 @@
323323
}
324324

325325

326-
/* card-icon 样式已移至 index.rst 中统一管理 */
326+
/* =========================================================
327+
独立社区侧边栏专属样式
328+
========================================================= */
329+
330+
#independent-sidebar .custom-sidebar-caption {
331+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
332+
font-size: 85%;
333+
color: #0066cc;
334+
font-weight: 700;
335+
text-transform: uppercase;
336+
margin-top: 1.5em;
337+
margin-bottom: 0.5em;
338+
padding-left: 15px;
339+
letter-spacing: 0.5px;
340+
}
341+
342+
#independent-sidebar ul {
343+
margin-bottom: 0 !important;
344+
}
345+
346+
/* 覆盖菜单基础项的 padding,使其靠左贴齐 */
347+
#independent-sidebar ul li.toctree-l1 > a {
348+
padding-left: 15px !important;
349+
}
350+
351+
#independent-sidebar ul li.toctree-l1.current > a {
352+
background: #e6f0fa; /* 当前选中项高亮背景色 */
353+
color: #0066cc;
354+
border-left: 4px solid #0066cc;
355+
padding-left: 11px !important; /* 减去边框宽度保持对齐 */
356+
}

_templates/layout.html

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
{% extends "!layout.html" %}
2+
3+
{% block menu %}
4+
{% if is_independent %}
5+
<!-- 1. 将原本庞大的全局菜单隐藏起来,作为数据源 -->
6+
<div id="temp-menu-holder" style="display: none;">
7+
{{ super() }}
8+
</div>
9+
10+
<!-- 2. 独立站点独立侧边栏容器(直接插入在原菜单位置) -->
11+
<div id="independent-sidebar"></div>
12+
13+
<script>
14+
document.addEventListener('DOMContentLoaded', function() {
15+
const mapping = {{ comm_config.get('sidebar_mapping', {}) | tojson | safe }};
16+
const commId = '{{ current_community_id }}';
17+
18+
// 获取数据源和目标容器
19+
const globalMenu = document.getElementById('temp-menu-holder');
20+
const targetContainer = document.getElementById('independent-sidebar');
21+
22+
if (!globalMenu) return;
23+
24+
// 步骤 A: 找到当前社区的主节点 (通常带有 .current 类)
25+
let activeL1 = globalMenu.querySelector('li.toctree-l1.current');
26+
27+
// 兜底策略: 如果没有 .current (如强制刷新等边缘情况),通过链接匹配
28+
if (!activeL1 || !activeL1.querySelector('a').href.includes('/sources/' + commId + '/')) {
29+
const links = globalMenu.querySelectorAll('li.toctree-l1 > a');
30+
for (let i = 0; i < links.length; i++) {
31+
if (links[i].href.includes('/sources/' + commId + '/')) {
32+
activeL1 = links[i].closest('li');
33+
break;
34+
}
35+
}
36+
}
37+
38+
if (activeL1) {
39+
// 步骤 B: 找到属于这个社区的所有子页面 (<ul>)
40+
const subMenu = activeL1.querySelector('ul');
41+
42+
if (subMenu && subMenu.children.length > 0) {
43+
let currentGroup = null;
44+
let currentUl = null;
45+
46+
// 步骤 C: 遍历所有的子页面,将它们分组并插入到独立侧边栏中
47+
const items = Array.from(subMenu.children);
48+
items.forEach(item => {
49+
if (item.tagName.toLowerCase() !== 'li') return;
50+
51+
const link = item.querySelector('a');
52+
if (!link) return;
53+
54+
const fullUrl = link.href;
55+
let matchedFolder = null;
56+
57+
// 匹配 conf.py 中配置的文件夹路径
58+
for (const folder in mapping) {
59+
if (fullUrl.includes('/' + folder + '/')) {
60+
matchedFolder = folder;
61+
break;
62+
}
63+
}
64+
65+
// 如果有的文件放在根目录没匹配到,归入 default
66+
if (!matchedFolder) {
67+
matchedFolder = currentGroup || 'default';
68+
}
69+
70+
// 步骤 D: 遇到新分组时,创建大标题和新的 <ul>
71+
if (currentGroup !== matchedFolder) {
72+
if (mapping[matchedFolder]) {
73+
const caption = document.createElement('p');
74+
caption.className = 'caption custom-sidebar-caption';
75+
caption.innerHTML = `<span class="caption-text">${mapping[matchedFolder]}</span>`;
76+
targetContainer.appendChild(caption);
77+
}
78+
79+
currentUl = document.createElement('ul');
80+
targetContainer.appendChild(currentUl);
81+
currentGroup = matchedFolder;
82+
}
83+
84+
// 步骤 E: 智能动态提升整棵树的级数,完美支持长文档的内部 H2/H3 目录显示
85+
// 找出该节点及其内部所有的级联列表项
86+
const allTocItems = [item, ...item.querySelectorAll('[class*="toctree-l"]')];
87+
allTocItems.forEach(el => {
88+
// 将 toctree-l(X) 动态替换为 toctree-l(X-1)
89+
el.className = el.className.replace(/toctree-l(\d+)/g, function(match, level) {
90+
const newLevel = parseInt(level, 10) - 1;
91+
return 'toctree-l' + newLevel;
92+
});
93+
});
94+
95+
// 挂载到对应独立社区的菜单中
96+
if (currentUl) {
97+
currentUl.appendChild(item);
98+
}
99+
});
100+
101+
// 步骤 F: 彻底删除隐蔽的全局菜单
102+
globalMenu.remove();
103+
return;
104+
}
105+
}
106+
107+
// 异常兜底: 如果出现极端的解析失败(比如网络延迟),取消隐藏,确保文档菜单可用
108+
globalMenu.style.display = 'block';
109+
});
110+
</script>
111+
{% else %}
112+
<!-- 非独立社区页面,直接按普通 Sphinx 逻辑渲染 -->
113+
{{ super() }}
114+
{% endif %}
115+
{% endblock %}

conf.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,33 @@
3030
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
3131
# ones.
3232
extensions = [
33-
'recommonmark',
33+
# 'recommonmark',
3434
'sphinx.ext.autodoc',
3535
'sphinxext.remoteliteralinclude',
3636
'sphinx_copybutton',
3737
'sphinx_markdown_tables',
3838
"sphinx_design",
39+
'myst_parser',
3940
]
4041

42+
# 这一行非常重要,它允许 MyST 处理复杂的标题层级
43+
myst_heading_anchors = 3
44+
45+
# 允许在 RST 中嵌入 Markdown 内容
46+
myst_enable_extensions = [
47+
"colon_fence",
48+
"html_image",
49+
]
50+
51+
# conf.py
52+
html_theme_options = {
53+
# 仅显示当前页面所属的导航树,不显示全局无关节点
54+
'collapse_navigation': True,
55+
'navigation_depth': 4,
56+
'includehidden': True,
57+
'titles_only': False,
58+
}
59+
4160
# 模板路径设置
4261
templates_path = ['_templates']
4362
autosummary_generate = True
@@ -179,6 +198,57 @@ def generate_api_doc():
179198
with open(rst_filename, 'w', encoding='utf-8') as f:
180199
f.write(rendered_content)
181200

201+
# =========================================================
202+
# 独立社区页面全局配置 (核心机制:高度可配置化)
203+
# =========================================================
204+
html_context = {
205+
'independent_communities': {
206+
'verl': {
207+
'display_name': 'verl',
208+
'sidebar_mapping': {
209+
'onboarding_getting_started': '🚀 启航入门',
210+
'core_features_application_guide': '📚 应用指南',
211+
'porting_performance_tuning': '⚡ 适配与调优',
212+
'faq':'🔆 故障排查(FAQ)',
213+
'open_source_development': '🔧 开源开发'
214+
}
215+
},
216+
# 未来增加 sglang,只需在这里解除注释即可,不用改代码
217+
# 'sglang': {
218+
# 'display_name': 'SGLANG',
219+
# 'sidebar_mapping': {
220+
# 'quick_start': '🚀 快速开始',
221+
# 'api_reference': '📖 API 参考'
222+
# }
223+
# }
224+
}
225+
}
226+
227+
# 【新增核心代码】:Sphinx 页面上下文注入 Hook
228+
def update_page_context(app, pagename, templatename, context, doctree):
229+
"""
230+
拦截页面渲染,判断当前路径是否属于独立社区。
231+
如果是,向 Jinja 模板注入 is_independent 和对应的 comm_config 变量。
232+
"""
233+
communities = context.get('independent_communities', {})
234+
context['is_independent'] = False
235+
236+
# 根据路径匹配,如 'sources/verl/index'
237+
for comm_id, comm_info in communities.items():
238+
if pagename.startswith(f"sources/{comm_id}"):
239+
context['is_independent'] = True
240+
context['current_community_id'] = comm_id
241+
context['comm_config'] = comm_info
242+
break
243+
244+
def setup(app):
245+
app.add_css_file('custom.css')
246+
app.add_js_file('package_info.js')
247+
app.add_js_file('statistics.js')
248+
249+
# 【新增 Hook 注册】
250+
app.connect('html-page-context', update_page_context)
251+
182252
# 在 Sphinx 构建之前调用该函数生成 API 文档
183253
try:
184254
generate_api_doc()

index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
<div class="project-card">
208208
<div class="card-top"><div class="card-icon" style="background-image: url('_static/images/volcano.png')"></div><h3 class="card-title">verl</h3></div>
209209
<p class="card-desc">用于 LLM 的强化学习训练库,适配昇腾并行计算方案。</p>
210-
<div class="card-footer"><a href="https://github.com/volcengine/verl">官方链接</a><span class="split">|</span><a href="sources/_generated/sources/verl/ascend_quick_start.html">安装指南</a><span class="split">|</span><a href="sources/_generated/sources/verl/ascend_quick_start.html">快速上手</a></div>
210+
<div class="card-footer"><a href="https://github.com/volcengine/verl">官方链接</a><span class="split">|</span><a href="sources/verl/optimization/ascend_quick_start.html">安装指南</a><span class="split">|</span><a href="sources/verl/get_started/quickstart.html">快速上手</a></div>
211211
</div>
212212

213213
</div>

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ sphinx_markdown_tables
88
sphinx-design
99
torch==2.5.1+cpu; platform_machine == "x86_64"
1010
torch==2.5.1; platform_machine == "aarch64"
11-
torch_npu==2.5.1rc1; sys_platform == "linux"
11+
torch_npu==2.5.1rc1;sys_platform == "linux"
12+
myst_parser
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
3+
.. include:: ../../_generated/sources/verl/features/ascend_backend_features.md
4+
:parser: myst_parser.sphinx_
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
.. include:: ../../_generated/sources/verl/examples/ascend_qwen3-langSeq_practices.md
3+
:parser: myst_parser.sphinx_
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
.. include:: ../../_generated/sources/verl/examples/ascend_retool_best_pratice.rst

0 commit comments

Comments
 (0)