diff --git a/doc/_extensions/zephyr/kconfig/__init__.py b/doc/_extensions/zephyr/kconfig/__init__.py index fe037d1c894..b947b91a9af 100644 --- a/doc/_extensions/zephyr/kconfig/__init__.py +++ b/doc/_extensions/zephyr/kconfig/__init__.py @@ -26,6 +26,10 @@ Options - kconfig_ext_paths: A list of base paths where to search for external modules Kconfig files when they use ``kconfig-ext: True``. The extension will look for ${BASE_PATH}/modules/${MODULE_NAME}/Kconfig. +- kconfig_gh_link_base_url: The base URL for the GitHub links. This is used to + generate links to the Kconfig files on GitHub. +- kconfig_zephyr_version: The Zephyr version. This is used to generate links to + the Kconfig files on GitHub. """ import argparse @@ -429,8 +433,14 @@ def kconfig_build_resources(app: Sphinx) -> None: kconfig_db_file = outdir / "kconfig.json" + kconfig_db = { + "gh_base_url": app.config.kconfig_gh_link_base_url, + "zephyr_version": app.config.kconfig_zephyr_version, + "symbols": db, + } + with open(kconfig_db_file, "w") as f: - json.dump(db, f) + json.dump(kconfig_db, f) app.config.html_extra_path.append(kconfig_db_file.as_posix()) app.config.html_static_path.append(RESOURCES_DIR.as_posix()) @@ -461,6 +471,8 @@ def kconfig_install( def setup(app: Sphinx): app.add_config_value("kconfig_generate_db", False, "env") app.add_config_value("kconfig_ext_paths", [], "env") + app.add_config_value("kconfig_gh_link_base_url", "", "") + app.add_config_value("kconfig_zephyr_version", "", "") app.add_node( KconfigSearchNode, diff --git a/doc/_extensions/zephyr/kconfig/static/kconfig.mjs b/doc/_extensions/zephyr/kconfig/static/kconfig.mjs index 6c94845a107..f76bf8baa92 100644 --- a/doc/_extensions/zephyr/kconfig/static/kconfig.mjs +++ b/doc/_extensions/zephyr/kconfig/static/kconfig.mjs @@ -5,6 +5,8 @@ const DB_FILE = 'kconfig.json'; const RESULTS_PER_PAGE_OPTIONS = [10, 25, 50]; +let zephyr_gh_base_url; +let zephyr_version; /* search state */ let db; @@ -57,13 +59,38 @@ function showProgress(message) { p.appendChild(pText); } +/** + * Generate a GitHub link for a given file path in the Zephyr repository. + * @param {string} path - The file path in the repository. + * @param {number} [line] - Optional line number to link to. + * @param {string} [mode=blob] - The mode (blob or edit). Defaults to 'blob'. + * @param {string} [revision=main] - The branch, tag, or commit hash. Defaults to 'main'. + * @returns {string} - The generated GitHub URL. + */ +function getGithubLink(path, line, mode = "blob", revision = "main") { + let url = [ + zephyr_gh_base_url, + mode, + revision, + path + ].join("/"); + + if (line !== undefined){ + url += `#L${line}`; + } + + return url; +} + + /** * Render a Kconfig literal property. * @param {Element} parent Parent element. * @param {String} title Title. - * @param {String} content Content. + * @param {Element} contentElement Content Element. */ -function renderKconfigPropLiteral(parent, title, content) { +function renderKconfigPropLiteralElement(parent, title, contentElement) +{ const term = document.createElement('dt'); parent.appendChild(term); @@ -81,8 +108,18 @@ function renderKconfigPropLiteral(parent, title, content) { literal.className = 'pre'; code.appendChild(literal); - const literalText = document.createTextNode(content); - literal.appendChild(literalText); + literal.appendChild(contentElement); +} + +/** + * Render a Kconfig literal property. + * @param {Element} parent Parent element. + * @param {String} title Title. + * @param {String} content Content. + */ +function renderKconfigPropLiteral(parent, title, content) { + const contentElement = document.createTextNode(content); + renderKconfigPropLiteralElement(parent, title, contentElement); } /** @@ -268,7 +305,17 @@ function renderKconfigEntry(entry) { renderKconfigPropList(props, 'Implied by', entry.implied_by, true); renderKconfigPropList(props, 'Ranges', entry.ranges, false); renderKconfigPropList(props, 'Choices', entry.choices, false); - renderKconfigPropLiteral(props, 'Location', `${entry.filename}:${entry.linenr}`); + + /* symbol location with permalink */ + const locationPermalink = document.createElement('a'); + locationPermalink.href = getGithubLink(entry.filename, entry.linenr, "blob", zephyr_version); + + const locationElement = document.createTextNode(`${entry.filename}:${entry.linenr}`); + locationElement.class = "pre"; + locationPermalink.appendChild(locationElement); + + renderKconfigPropLiteralElement(props, 'Location', locationPermalink); + renderKconfigPropLiteral(props, 'Menu path', entry.menupath); return container; @@ -483,7 +530,9 @@ function setupKconfigSearch() { fetch(DB_FILE) .then(response => response.json()) .then(json => { - db = json; + db = json["symbols"]; + zephyr_gh_base_url = json["gh_base_url"]; + zephyr_version = json["zephyr_version"]; results.replaceChildren(); diff --git a/doc/conf.py b/doc/conf.py index a8502872562..ba3e970adfc 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -299,6 +299,8 @@ gh_link_exclude = [ kconfig_generate_db = True kconfig_ext_paths = [ZEPHYR_BASE] +kconfig_gh_link_base_url = "https://github.com/zephyrproject-rtos/zephyr" +kconfig_zephyr_version = f"v{version}" if is_release else "main" # -- Options for zephyr.external_content ----------------------------------