conf.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. # Configuration file for the Sphinx documentation builder.
  2. #
  3. # This file only contains a selection of the most common options. For a full
  4. # list see the documentation:
  5. # https://www.sphinx-doc.org/en/master/usage/configuration.html
  6. # -- Path setup --------------------------------------------------------------
  7. # If extensions (or modules to document with autodoc) are in another directory,
  8. # add these directories to sys.path here. If the directory is relative to the
  9. # documentation root, use os.path.abspath to make it absolute, like shown here.
  10. #
  11. import os
  12. import sys
  13. import yaml
  14. sys.path.insert(0, os.path.abspath('..'))
  15. # 加载配置文件
  16. def load_config():
  17. """加载配置文件"""
  18. config_path = os.path.join(os.path.dirname(__file__), 'config.yaml')
  19. if os.path.exists(config_path):
  20. with open(config_path, 'r', encoding='utf-8') as f:
  21. return yaml.safe_load(f)
  22. return {}
  23. config = load_config()
  24. project_config = config.get('project', {})
  25. sphinx_config = config.get('sphinx', {})
  26. repository_config = config.get('repository', {})
  27. # -- Project information -----------------------------------------------------
  28. project = project_config.get('name', 'SDK_Docs')
  29. copyright = project_config.get('copyright', '2025, apache')
  30. author = project_config.get('author', 'unknown')
  31. # The full version, including alpha/beta/rc tags
  32. release = project_config.get('version', '0.0.1')
  33. # 动态设置主文档:优先使用环境变量,否则使用默认值
  34. import os
  35. master_doc = os.environ.get('SPHINX_MASTER_DOC', 'index_zh')
  36. # 如果通过命令行参数指定了master_doc,则使用命令行参数的值
  37. # 这需要在构建脚本中通过环境变量传递
  38. if 'SPHINX_MASTER_DOC_OVERRIDE' in os.environ:
  39. master_doc = os.environ['SPHINX_MASTER_DOC_OVERRIDE']
  40. # -- General configuration ---------------------------------------------------
  41. # Add any Sphinx extension module names here, as strings. They can be
  42. # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
  43. # ones.
  44. extensions = sphinx_config.get('extensions', ['myst_parser'])
  45. source_suffix = sphinx_config.get('source_suffix', {
  46. '.rst': 'restructuredtext',
  47. '.md': 'markdown',
  48. })
  49. # Add any paths that contain templates here, relative to this directory.
  50. templates_path = ['_templates']
  51. # The language for content autogenerated by Sphinx. Refer to documentation
  52. # for a list of supported languages.
  53. #
  54. # This is also used if you do content translation via gettext catalogs.
  55. # Usually you set "language" from the command line for these cases.
  56. # 优先使用环境变量,然后使用配置文件,最后使用默认值
  57. language = os.environ.get('SPHINX_LANGUAGE', project_config.get('language', 'zh_CN'))
  58. # List of patterns, relative to source directory, that match files and
  59. # directories to ignore when looking for source files.
  60. # This pattern also affects html_static_path and html_extra_path.
  61. # 基础排除模式
  62. base_exclude_patterns = [
  63. 'MIGRATION_GUIDE.md',
  64. 'OPTIMIZATION_SUMMARY.md',
  65. 'README_NEW_BUILD_SYSTEM.md',
  66. 'requirements.txt',
  67. 'utils/',
  68. '_templates/',
  69. '_static/',
  70. '_build/',
  71. ]
  72. # 根据环境变量设置文档排除模式
  73. exclude_patterns = base_exclude_patterns.copy()
  74. if 'SPHINX_EXCLUDE_PATTERNS' in os.environ:
  75. env_exclude_patterns = os.environ['SPHINX_EXCLUDE_PATTERNS'].split(',')
  76. env_exclude_patterns = [pattern.strip() for pattern in env_exclude_patterns if pattern.strip()]
  77. exclude_patterns.extend(env_exclude_patterns)
  78. # 调试信息
  79. print(f"DEBUG: master_doc = {master_doc}")
  80. print(f"DEBUG: language = {language}")
  81. print(f"DEBUG: exclude_patterns = {exclude_patterns}")
  82. # -- Options for HTML output -------------------------------------------------
  83. # The theme to use for HTML and HTML Help pages. See the documentation
  84. # for a list of builtin themes.
  85. #
  86. html_theme = sphinx_config.get('theme', 'sphinx_rtd_theme')
  87. # Add any paths that contain custom static files (such as style sheets) here,
  88. # relative to this directory. They are copied after the builtin static files,
  89. # so a file named "default.css" will overwrite the builtin "default.css".
  90. html_static_path = ['_static']
  91. # -- Options for internationalization ----------------------------------------
  92. # 多语言支持配置
  93. # locale_dirs = ['../docs/locale/']
  94. # gettext_compact = False
  95. # -- MyST Parser configuration ----------------------------------------------
  96. myst_enable_extensions = sphinx_config.get('myst_extensions', [
  97. "colon_fence",
  98. "deflist",
  99. "dollarmath",
  100. "html_image",
  101. "html_admonition",
  102. "replacements",
  103. "smartquotes",
  104. "strikethrough",
  105. "substitution",
  106. "tasklist",
  107. ])
  108. # MyST图片配置
  109. myst_gfm_only = False
  110. myst_heading_anchors = 0
  111. # 配置图片处理
  112. myst_all_links_external = False
  113. myst_url_schemes = ('http', 'https', 'mailto', 'ftp')
  114. # 图片路径配置
  115. html_extra_path = []
  116. html_css_files = ['version_menu.css', 'custom.css', 'pdf_button.css', 'edit_button.css', 'language_switch.css', 'dark_mode.css']
  117. html_js_files = ['version_menu.js', 'download_pdf.js', 'version_info.js', 'edit_on_github.js', 'language_switch.js']
  118. # 配置图片路径处理
  119. html_favicon = None
  120. # 配置文档结构
  121. html_show_sourcelink = False
  122. html_show_sphinx = False
  123. html_show_copyright = True
  124. # 配置导航
  125. html_theme_options = {
  126. 'navigation_depth': 4,
  127. 'titles_only': False,
  128. 'collapse_navigation': False,
  129. 'sticky_navigation': True,
  130. 'includehidden': True,
  131. }
  132. # 配置文档结构
  133. html_use_index = True
  134. html_split_index = False
  135. html_copy_source = False
  136. # 配置导航结构
  137. html_sidebars = {
  138. '**': [
  139. 'globaltoc.html',
  140. 'relations.html',
  141. 'sourcelink.html',
  142. 'searchbox.html',
  143. ]
  144. }
  145. # 配置toctree选项
  146. html_use_index = True
  147. html_split_index = False
  148. html_copy_source = False
  149. # 检测构建环境并配置URL
  150. import os
  151. is_github_actions = os.environ.get('GITHUB_ACTIONS') == 'true'
  152. if is_github_actions:
  153. # GitHub Pages环境:使用相对URL
  154. html_use_relative_urls = True
  155. html_baseurl = ""
  156. else:
  157. # 本地构建环境:使用相对URL,但禁用canonical链接
  158. html_use_relative_urls = True
  159. html_baseurl = ""
  160. # 禁用canonical链接以避免错误的绝对路径
  161. html_show_sourcelink = False
  162. # 传递编辑基础 URL 给模板/前端脚本
  163. def derive_edit_base_url():
  164. # 优先使用 config.yaml 显式配置
  165. explicit = (repository_config.get('edit_base_url', '') or '').strip()
  166. if explicit:
  167. return explicit.rstrip('/') + '/'
  168. # 其后尝试从 GitHub Actions 环境变量推断(owner/repo)
  169. gh_repo = os.environ.get('GITHUB_REPOSITORY', '').strip() # e.g. owner/name
  170. if gh_repo and '/' in gh_repo:
  171. return f"https://github.com/{gh_repo}/edit/"
  172. # 再其次,从 git remote.origin.url 推断
  173. try:
  174. import subprocess
  175. origin = subprocess.run(['git', 'config', '--get', 'remote.origin.url'],
  176. capture_output=True, text=True, check=True).stdout.strip()
  177. if origin:
  178. if origin.startswith('git@') and 'github.com:' in origin:
  179. # git@github.com:owner/repo.git
  180. repo_path = origin.split('github.com:')[-1]
  181. repo_path = repo_path[:-4] if repo_path.endswith('.git') else repo_path
  182. return f"https://github.com/{repo_path}/edit/"
  183. if origin.startswith('https://') and 'github.com' in origin:
  184. # https://github.com/owner/repo.git
  185. repo_path = origin.split('github.com/')[-1]
  186. repo_path = repo_path[:-4] if repo_path.endswith('.git') else repo_path
  187. return f"https://github.com/{repo_path}/edit/"
  188. except Exception:
  189. pass
  190. # 最后兜底:使用 repository.name(无法确定 owner,仅供部分场景)
  191. repo_name = (repository_config.get('name', '') or '').strip()
  192. if repo_name:
  193. return f"https://github.com/{repo_name}/edit/"
  194. return ''
  195. html_context = {
  196. 'edit_base_url': derive_edit_base_url(),
  197. }
  198. """
  199. LaTeX / PDF 构建配置
  200. """
  201. # 使用 XeLaTeX 以更好支持 CJK 字体
  202. latex_engine = 'xelatex'
  203. # 配置 LaTeX 文档元信息与固定主文档名,便于脚本查找
  204. latex_documents = [
  205. # (source start file, target name, title, author, documentclass)
  206. ('index', 'sdk-docs.tex', project, author, 'manual'),
  207. ]
  208. # 额外 LaTeX 元素:引入中文字体与更好的换行支持
  209. latex_elements = {
  210. 'preamble': r'''
  211. % CJK 支持
  212. \usepackage{xeCJK}
  213. \setCJKmainfont{Noto Sans CJK SC}
  214. \setCJKsansfont{Noto Sans CJK SC}
  215. \setCJKmonofont{Noto Sans Mono CJK SC}
  216. % 改善中文行距与段落
  217. \linespread{1.2}
  218. ''',
  219. }