mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add `allow_section_headings
` to SphinxDirective parsing methods (#12503)
This commit is contained in:
parent
9276639fa6
commit
24a0385997
@ -278,7 +278,8 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
||||
# needed for association of version{added,changed} directives
|
||||
self.env.temp_data['object'] = self.names[0]
|
||||
self.before_content()
|
||||
content_node = addnodes.desc_content('', *self.parse_content_to_nodes())
|
||||
content_children = self.parse_content_to_nodes(allow_section_headings=True)
|
||||
content_node = addnodes.desc_content('', *content_children)
|
||||
node.append(content_node)
|
||||
self.transform_content(content_node)
|
||||
self.env.app.emit('object-description-transform',
|
||||
|
@ -311,7 +311,7 @@ class JSModule(SphinxDirective):
|
||||
self.env.ref_context['js:module'] = mod_name
|
||||
no_index = 'no-index' in self.options or 'noindex' in self.options
|
||||
|
||||
content_nodes = self.parse_content_to_nodes()
|
||||
content_nodes = self.parse_content_to_nodes(allow_section_headings=True)
|
||||
|
||||
ret: list[Node] = []
|
||||
if not no_index:
|
||||
|
@ -416,7 +416,7 @@ class PyModule(SphinxDirective):
|
||||
no_index = 'no-index' in self.options or 'noindex' in self.options
|
||||
self.env.ref_context['py:module'] = modname
|
||||
|
||||
content_nodes = self.parse_content_to_nodes()
|
||||
content_nodes = self.parse_content_to_nodes(allow_section_headings=True)
|
||||
|
||||
ret: list[Node] = []
|
||||
if not no_index:
|
||||
|
@ -405,7 +405,9 @@ class Glossary(SphinxDirective):
|
||||
|
||||
if definition:
|
||||
offset = definition.items[0][1]
|
||||
definition_nodes = nested_parse_to_nodes(self.state, definition, offset=offset)
|
||||
definition_nodes = nested_parse_to_nodes(
|
||||
self.state, definition, offset=offset, allow_section_headings=False,
|
||||
)
|
||||
else:
|
||||
definition_nodes = []
|
||||
termnodes.append(nodes.definition('', *definition_nodes))
|
||||
|
@ -409,7 +409,8 @@ class Autosummary(SphinxDirective):
|
||||
for text in column_texts:
|
||||
vl = StringList([text], f'{source}:{line}:<autosummary>')
|
||||
with switch_source_input(self.state, vl):
|
||||
col_nodes = nested_parse_to_nodes(self.state, vl)
|
||||
col_nodes = nested_parse_to_nodes(self.state, vl,
|
||||
allow_section_headings=False)
|
||||
if col_nodes and isinstance(col_nodes[0], nodes.paragraph):
|
||||
node = col_nodes[0]
|
||||
else:
|
||||
|
@ -47,7 +47,7 @@ class IfConfig(SphinxDirective):
|
||||
node.document = self.state.document
|
||||
self.set_source_info(node)
|
||||
node['expr'] = self.arguments[0]
|
||||
node += self.parse_content_to_nodes()
|
||||
node += self.parse_content_to_nodes(allow_section_headings=True)
|
||||
return [node]
|
||||
|
||||
|
||||
|
@ -434,21 +434,49 @@ class SphinxDirective(Directive):
|
||||
return f'<unknown>:{line}'
|
||||
return ''
|
||||
|
||||
def parse_content_to_nodes(self) -> list[Node]:
|
||||
"""Parse the directive's content into nodes."""
|
||||
return nested_parse_to_nodes(self.state, self.content, offset=self.content_offset)
|
||||
def parse_content_to_nodes(self, allow_section_headings: bool = False) -> list[Node]:
|
||||
"""Parse the directive's content into nodes.
|
||||
|
||||
def parse_text_to_nodes(self, text: str = '', /, *, offset: int = -1) -> list[Node]:
|
||||
:param allow_section_headings:
|
||||
Are titles (sections) allowed in the directive's content?
|
||||
Note that this option bypasses Docutils' usual checks on
|
||||
doctree structure, and misuse of this option can lead to
|
||||
an incoherent doctree. In Docutils, section nodes should
|
||||
only be children of ``Structural`` nodes, which includes
|
||||
``document``, ``section``, and ``sidebar`` nodes.
|
||||
"""
|
||||
return nested_parse_to_nodes(
|
||||
self.state,
|
||||
self.content,
|
||||
offset=self.content_offset,
|
||||
allow_section_headings=allow_section_headings,
|
||||
)
|
||||
|
||||
def parse_text_to_nodes(
|
||||
self, text: str = '', /, *, offset: int = -1, allow_section_headings: bool = False,
|
||||
) -> list[Node]:
|
||||
"""Parse *text* into nodes.
|
||||
|
||||
:param text:
|
||||
Text, in string form. ``StringList`` is also accepted.
|
||||
:param allow_section_headings:
|
||||
Are titles (sections) allowed in *text*?
|
||||
Note that this option bypasses Docutils' usual checks on
|
||||
doctree structure, and misuse of this option can lead to
|
||||
an incoherent doctree. In Docutils, section nodes should
|
||||
only be children of ``Structural`` nodes, which includes
|
||||
``document``, ``section``, and ``sidebar`` nodes.
|
||||
:param offset:
|
||||
The offset of the content.
|
||||
"""
|
||||
if offset == -1:
|
||||
offset = self.content_offset
|
||||
return nested_parse_to_nodes(self.state, text, offset=offset)
|
||||
return nested_parse_to_nodes(
|
||||
self.state,
|
||||
text,
|
||||
offset=offset,
|
||||
allow_section_headings=allow_section_headings,
|
||||
)
|
||||
|
||||
def parse_inline(
|
||||
self, text: str, *, lineno: int = -1,
|
||||
|
@ -334,7 +334,7 @@ def nested_parse_with_titles(state: RSTState, content: StringList, node: Node,
|
||||
context, such as docstrings.
|
||||
|
||||
This function is retained for compatability and will be deprecated in
|
||||
Sphinx 8. Prefer ``parse_block_text()``.
|
||||
Sphinx 8. Prefer ``nested_parse_to_nodes()``.
|
||||
"""
|
||||
with _fresh_title_style_context(state):
|
||||
ret = state.nested_parse(content, content_offset, node, match_titles=True)
|
||||
|
@ -20,6 +20,7 @@ def nested_parse_to_nodes(
|
||||
*,
|
||||
source: str = '<generated text>',
|
||||
offset: int = 0,
|
||||
allow_section_headings: bool = True,
|
||||
keep_title_context: bool = False,
|
||||
) -> list[nodes.Node]: # Element | nodes.Text
|
||||
"""Parse *text* into nodes.
|
||||
@ -32,6 +33,13 @@ def nested_parse_to_nodes(
|
||||
The text's source, used when creating a new ``StringList``.
|
||||
:param offset:
|
||||
The offset of the content.
|
||||
:param allow_section_headings:
|
||||
Are titles (sections) allowed in *text*?
|
||||
Note that this option bypasses Docutils' usual checks on
|
||||
doctree structure, and misuse of this option can lead to
|
||||
an incoherent doctree. In Docutils, section nodes should
|
||||
only be children of ``Structural`` nodes, which includes
|
||||
``document``, ``section``, and ``sidebar`` nodes.
|
||||
:param keep_title_context:
|
||||
If this is False (the default), then *content* is parsed as if it were
|
||||
an independent document, meaning that title decorations (e.g. underlines)
|
||||
@ -49,10 +57,10 @@ def nested_parse_to_nodes(
|
||||
node.document = document
|
||||
|
||||
if keep_title_context:
|
||||
state.nested_parse(content, offset, node, match_titles=True)
|
||||
state.nested_parse(content, offset, node, match_titles=allow_section_headings)
|
||||
else:
|
||||
with _fresh_title_style_context(state):
|
||||
state.nested_parse(content, offset, node, match_titles=True)
|
||||
state.nested_parse(content, offset, node, match_titles=allow_section_headings)
|
||||
return node.children
|
||||
|
||||
|
||||
|
@ -100,7 +100,7 @@ def test_sphinx_directive_parse_content_to_nodes():
|
||||
content = 'spam\n====\n\nEggs! *Lobster thermidor.*'
|
||||
directive.content = StringList(content.split('\n'), source='<source>')
|
||||
|
||||
parsed = directive.parse_content_to_nodes()
|
||||
parsed = directive.parse_content_to_nodes(allow_section_headings=True)
|
||||
assert len(parsed) == 1
|
||||
node = parsed[0]
|
||||
assert isinstance(node, nodes.section)
|
||||
@ -115,7 +115,7 @@ def test_sphinx_directive_parse_text_to_nodes():
|
||||
directive = make_directive(env=SimpleNamespace())
|
||||
content = 'spam\n====\n\nEggs! *Lobster thermidor.*'
|
||||
|
||||
parsed = directive.parse_text_to_nodes(content)
|
||||
parsed = directive.parse_text_to_nodes(content, allow_section_headings=True)
|
||||
assert len(parsed) == 1
|
||||
node = parsed[0]
|
||||
assert isinstance(node, nodes.section)
|
||||
|
Loading…
Reference in New Issue
Block a user