From 5677a91e82a065d4d85d0c19cbb13e4d29fb5271 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Mon, 17 Mar 2025 01:42:01 +0100 Subject: [PATCH] Optimized subfolders --- sphinx/_templates/local_md_files.html | 14 +++++++- sphinx/extensions/local_subfolders.py | 48 ++++++++++++++------------- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/sphinx/_templates/local_md_files.html b/sphinx/_templates/local_md_files.html index d668758e..a44b6bef 100644 --- a/sphinx/_templates/local_md_files.html +++ b/sphinx/_templates/local_md_files.html @@ -13,7 +13,19 @@ {% if local_md_headings %}
-

Overview

+

Current Folder

{{ render_headings(local_md_headings) }}
{% endif %} + +{% if local_subfolders %} +
+

Subfolders

+ +
+{% endif %} + diff --git a/sphinx/extensions/local_subfolders.py b/sphinx/extensions/local_subfolders.py index 390561c1..50524836 100644 --- a/sphinx/extensions/local_subfolders.py +++ b/sphinx/extensions/local_subfolders.py @@ -1,7 +1,6 @@ import os import re from sphinx.util import logging -from docutils.parsers.rst import Directive from .nav_utils import natural_sort_key, extract_headings_from_file, group_headings, sort_tree, MAX_HEADING_LEVEL, DEFAULT_MAX_NAV_DEPTH logger = logging.getLogger(__name__) @@ -9,9 +8,11 @@ logger = logging.getLogger(__name__) def collect_subfolder_tree(dir_path, base_url, current_depth, max_depth): """ Recursively collects navigation items from subdirectories. - For each subfolder, it looks for a candidate file (prefer "index.rst" then "README.md") - and extracts its first level‑1 heading as the title. If no candidate or heading is found, - the folder name is used. + For each subfolder, it looks for a candidate file (prefer "index.rst" then "README.md"). + Only subfolders with such a file will be included. + If a candidate is found, the first level‑1 heading from that file is used as the title; + if no heading is found, the folder name is used. + The link is built pointing directly to the candidate file (by its base name) rather than the folder. Returns a list representing the subfolder tree. """ items = [] @@ -24,32 +25,34 @@ def collect_subfolder_tree(dir_path, base_url, current_depth, max_depth): if os.path.isfile(candidate_path): candidate = candidate_path break + # Only include the folder if a candidate file was found. if candidate: headings = extract_headings_from_file(candidate, max_level=MAX_HEADING_LEVEL) title = headings[0]['text'] if headings else item - else: - title = item - link = os.path.join(base_url, item) - entry = { - 'level': 1, - 'text': title, - 'link': link, - 'anchor': '', - 'priority': 0, - 'filename': item - } - if current_depth < max_depth: - children = collect_subfolder_tree(full_path, os.path.join(base_url, item), current_depth + 1, max_depth) - if children: - entry['children'] = children - items.append(entry) + # Use the candidate file's base name as link target. + candidate_base = os.path.splitext(os.path.basename(candidate))[0] + link = os.path.join(base_url, item, candidate_base) + entry = { + 'level': 1, + 'text': title, + 'link': link, + 'anchor': '', + 'priority': 0, + 'filename': item + } + if current_depth < max_depth: + children = collect_subfolder_tree(full_path, os.path.join(base_url, item), current_depth + 1, max_depth) + if children: + entry['children'] = children + items.append(entry) return items def add_local_subfolders(app, pagename, templatename, context, doctree): """ Collects a tree of subfolder navigation items from the current directory. - For each subfolder, the title is determined by scanning for a candidate file (prefer "index.rst" then "README.md") - and extracting its first level‑1 heading, or using the folder name if none is found. + For each subfolder, the title is determined by scanning for a candidate file + (prefer "index.rst" then "README.md") and extracting its first level‑1 heading, + or using the folder name if none is found. The resulting tree is stored in context['local_subfolders']. """ srcdir = app.srcdir @@ -66,6 +69,5 @@ def add_local_subfolders(app, pagename, templatename, context, doctree): context['local_subfolders'] = subfolder_tree def setup(app): - # Do not add the config value here to avoid conflicts. app.connect('html-page-context', add_local_subfolders) return {'version': '0.1', 'parallel_read_safe': True}