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 %}
+
+{% 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}