Skip to content
This repository was archived by the owner on Jul 21, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 6 additions & 42 deletions sphinx/directives/other.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from sphinx.util.docutils import SphinxDirective
from sphinx.util.matching import Matcher, patfilter
from sphinx.util.nodes import explicit_title_re, set_source_info, \
process_index_entry
process_index_entry, nested_parse_with_titles_and_toctree_support

if False:
# For type annotation
Expand All @@ -39,7 +39,6 @@ def int_or_nothing(argument):
return 999
return int(argument)


class TocTree(SphinxDirective):
"""
Directive to notify Sphinx about the hierarchical structure of the docs,
Expand Down Expand Up @@ -312,11 +311,15 @@ def run(self):
newnode += col
return [newnode]

# def support_nested_section_title():
# """explaining systr
# """

class Only(SphinxDirective):
"""
Directive to only include text if the given tag(s) are enabled.
"""
node_class = addnodes.only
has_content = True
required_arguments = 1
optional_arguments = 0
Expand All @@ -330,46 +333,7 @@ def run(self):
set_source_info(self, node)
node['expr'] = self.arguments[0]

# Same as util.nested_parse_with_titles but try to handle nested
# sections which should be raised higher up the doctree.
surrounding_title_styles = self.state.memo.title_styles
surrounding_section_level = self.state.memo.section_level
self.state.memo.title_styles = []
self.state.memo.section_level = 0
try:
self.state.nested_parse(self.content, self.content_offset,
node, match_titles=1)
title_styles = self.state.memo.title_styles
if (not surrounding_title_styles or
not title_styles or
title_styles[0] not in surrounding_title_styles or
not self.state.parent):
# No nested sections so no special handling needed.
return [node]
# Calculate the depths of the current and nested sections.
current_depth = 0
parent = self.state.parent
while parent:
current_depth += 1
parent = parent.parent
current_depth -= 2
title_style = title_styles[0]
nested_depth = len(surrounding_title_styles)
if title_style in surrounding_title_styles:
nested_depth = surrounding_title_styles.index(title_style)
# Use these depths to determine where the nested sections should
# be placed in the doctree.
n_sects_to_raise = current_depth - nested_depth + 1
parent = self.state.parent
for i in range(n_sects_to_raise):
if parent.parent:
parent = parent.parent
parent.append(node)
return []
finally:
self.state.memo.title_styles = surrounding_title_styles
self.state.memo.section_level = surrounding_section_level

return nested_parse_with_titles_and_toctree_support(self, node)

class Include(BaseInclude, SphinxDirective):
"""
Expand Down
2 changes: 1 addition & 1 deletion sphinx/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
SEP, os_path, relative_uri, ensuredir, walk, mtimes_of_files, movefile,
copyfile, copytimes, make_filename, ustrftime)
from sphinx.util.nodes import ( # noqa
nested_parse_with_titles, split_explicit_title, explicit_title_re,
nested_parse_with_titles, nested_parse_with_titles_and_toctree_support, split_explicit_title, explicit_title_re,
caption_ref_re)
from sphinx.util.matching import patfilter # noqa

Expand Down
56 changes: 56 additions & 0 deletions sphinx/util/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,62 @@ def nested_parse_with_titles(state, content, node):
state.memo.section_level = surrounding_section_level


def nested_parse_with_titles_and_toctree_support(directive, node):
"""Same as :py:func:`sphinx.util.nodes.nested_parse_with_titles` but try to handle nested
sections which should be raised higher up the doctree.

Sphinx uses this function in the directive
:py:class:`~sphinx.directives.other.Only` but can be reused in any
custom extension that intends to support nested sections while preventing docutils from injecting :py:class:`~docutils.nodes.system_message` with ``WARNING: Unexpected section title.``.

.. important:: this function is meant to be used within the ``def
run(self):`` method of Sphinx directives as it returns a result.

:param directive: an instance of :py:class:`SphinxDirective`
:param node: an instance of a node created by the directive
:returns: a list of nodes (which can be empty depending on tha case)
"""
surrounding_title_styles = directive.state.memo.title_styles
surrounding_section_level = directive.state.memo.section_level

directive.state.memo.title_styles = []
directive.state.memo.section_level = 0

try:
directive.state.nested_parse(directive.content, directive.content_offset,
node, match_titles=1)
title_styles = directive.state.memo.title_styles
if (not surrounding_title_styles or
not title_styles or
title_styles[0] not in surrounding_title_styles or
not directive.state.parent):
# No nested sections so no special handling needed.
return [node]
# Calculate the depths of the current and nested sections.
current_depth = 0
parent = directive.state.parent
while parent:
current_depth += 1
parent = parent.parent
current_depth -= 2
title_style = title_styles[0]
nested_depth = len(surrounding_title_styles)
if title_style in surrounding_title_styles:
nested_depth = surrounding_title_styles.index(title_style)
# Use these depths to determine where the nested sections should
# be placed in the doctree.
n_sects_to_raise = current_depth - nested_depth + 1
parent = directive.state.parent
for i in range(n_sects_to_raise):
if parent.parent:
parent = parent.parent
parent.append(node)
return []

finally:
directive.state.memo.title_styles = surrounding_title_styles
directive.state.memo.section_level = surrounding_section_level

def clean_astext(node):
# type: (nodes.Node) -> unicode
"""Like node.astext(), but ignore images."""
Expand Down