如何在网站根目录非域名时获取文档站根路径?
我正在为文档构建器开发版本切换器,需求是:当用户访问的页面在旧版本中不存在时,自动重定向到对应版本的文档根目录。
举个例子:当前页面是https://pydata-sphinx-theme.readthedocs.io/en/stable/examples/index.html,但该页面在v0.9版本中不存在,用户切换到v0.9时,应该被重定向到https://pydata-sphinx-theme.readthedocs.io/en/v0.9.0/。
核心难点在于文档构建环境存在差异(本地、Read the Docs等第三方工具),导致网站根目录的结构不一致。我尝试了以下JavaScript代码来处理URL:
/** * Check if the corresponding url is absolute and make a absolute path from root if necessary * * @param {string} url the url to check */ function makeAbsoluteUrl(url) { // Regular expression pattern to match relative URLs const pattern = /^(?!(?:[a-z]+:)?\/\/)/i; const base_url = window.location.origin; url = pattern.test(url) ? base_url + "/" + url : url; return url; }
但问题在于Read the Docs(RDT)的构建环境中,网站根目录并非window.location.origin。比如在PR预览环境中,页面初始地址是https://pydata-sphinx-theme--1344.org.readthedocs.build/en/1344/,此时正确的根路径应该是en/1344/,而非https://pydata-sphinx-theme--1344.org.readthedocs.build。
请问能否从页面中推断出正确的根目录?
解决方案
方法1:利用Sphinx生成的根路径元数据(推荐)
Sphinx构建的文档可通过自定义模板在页面头部注入根路径标识,比如在_templates/layout.html中添加:
<meta name="docs-root-path" content="{{ pathto('', 1) }}">
之后在JS中读取该元标签的值即可获取适配环境的根路径:
function getDocsRootPath() { const metaTag = document.querySelector('meta[name="docs-root-path"]'); return metaTag ? metaTag.getAttribute('content') : '/'; }
这种方式无需依赖URL结构,适配所有Sphinx构建的环境。
方法2:解析URL路径片段推断根目录
针对RDT和本地环境的路径特征,通过截取URL路径片段获取根目录:
function inferDocsRootPath() { const pathSegments = window.location.pathname.split('/').filter(seg => seg !== ''); let rootSegments = []; // 适配RDT结构:/语言/版本/... if (pathSegments.length >= 2) { rootSegments = pathSegments.slice(0, 2); } // 适配本地结构:/版本/... 或根目录 else if (pathSegments.length >= 1) { rootSegments = pathSegments.slice(0, 1); } return rootSegments.join('/') + '/'; }
该方法无需修改模板,但需根据不同环境的路径规则调整片段截取逻辑。
方法3:生成绝对根URL
如果需要跳转绝对路径,可通过匹配URL中的版本/语言片段生成:
function getAbsoluteDocsRoot() { const currentPath = window.location.pathname; // 匹配语言+版本或单独版本的根路径 const rootMatch = currentPath.match(/^\/([a-z]+\/[a-z0-9.-]+\/)/i) || currentPath.match(/^\/([a-z0-9.-]+\/)/i); return rootMatch ? window.location.origin + rootMatch[1] : window.location.origin + '/'; }
内容的提问来源于stack exchange,提问作者Pierrick Rambaud

