mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add the `:no-typesetting:
` option for only creating targets (#10478)
Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
parent
05a14ff007
commit
97d2c5da2f
3
CHANGES
3
CHANGES
@ -29,6 +29,9 @@ Features added
|
||||
* #6319: viewcode: Add :confval:`viewcode_line_numbers` to control
|
||||
whether line numbers are added to rendered source code.
|
||||
Patch by Ben Krikler.
|
||||
* #9662: Add the ``:no-typesetting:`` option to suppress textual output
|
||||
and only create a linkable anchor.
|
||||
Patch by Latosha Maltba.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
@ -54,6 +54,9 @@ can give the directive option flag ``:nocontentsentry:``.
|
||||
If you want to typeset an object description, without even making it available
|
||||
for cross-referencing, you can give the directive option flag ``:noindex:``
|
||||
(which implies ``:noindexentry:``).
|
||||
If you do not want to typeset anything, you can give the directive option flag
|
||||
``:no-typesetting:``. This can for example be used to create only a target and
|
||||
index entry for later reference.
|
||||
Though, note that not every directive in every domain may support these
|
||||
options.
|
||||
|
||||
@ -65,6 +68,10 @@ options.
|
||||
The directive option ``:nocontentsentry:`` in the Python, C, C++, Javascript,
|
||||
and reStructuredText domains.
|
||||
|
||||
.. versionadded:: 7.2
|
||||
The directive option ``no-typesetting`` in the Python, C, C++, Javascript,
|
||||
and reStructuredText domains.
|
||||
|
||||
An example using a Python domain directive::
|
||||
|
||||
.. py:function:: spam(eggs)
|
||||
@ -91,6 +98,23 @@ you could say ::
|
||||
As you can see, both directive and role names contain the domain name and the
|
||||
directive name.
|
||||
|
||||
The directive option ``:no-typesetting:`` can be used to create a target
|
||||
(and index entry) which can later be referenced
|
||||
by the roles provided by the domain.
|
||||
This is particularly useful for literate programming:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. py:function:: spam(eggs)
|
||||
:no-typesetting:
|
||||
|
||||
.. code::
|
||||
|
||||
def spam(eggs):
|
||||
pass
|
||||
|
||||
The function :py:func:`spam` does nothing.
|
||||
|
||||
.. rubric:: Default Domain
|
||||
|
||||
For documentation describing objects from solely one domain, authors will not
|
||||
|
@ -57,6 +57,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
||||
'noindex': directives.flag,
|
||||
'noindexentry': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
}
|
||||
|
||||
# types of doc fields that this directive handles, see sphinx.util.docfields
|
||||
@ -218,6 +219,7 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
||||
node['noindex'] = noindex = ('noindex' in self.options)
|
||||
node['noindexentry'] = ('noindexentry' in self.options)
|
||||
node['nocontentsentry'] = ('nocontentsentry' in self.options)
|
||||
node['no-typesetting'] = ('no-typesetting' in self.options)
|
||||
if self.domain:
|
||||
node['classes'].append(self.domain)
|
||||
node['classes'].append(node['objtype'])
|
||||
@ -270,6 +272,19 @@ class ObjectDescription(SphinxDirective, Generic[ObjDescT]):
|
||||
DocFieldTransformer(self).transform_all(contentnode)
|
||||
self.env.temp_data['object'] = None
|
||||
self.after_content()
|
||||
|
||||
if node['no-typesetting']:
|
||||
# Attempt to return the index node, and a new target node
|
||||
# containing all the ids of this node and its children.
|
||||
# If ``:noindex:`` is set, or there are no ids on the node
|
||||
# or any of its children, then just return the index node,
|
||||
# as Docutils expects a target node to have at least one id.
|
||||
if node_ids := [node_id for el in node.findall(nodes.Element)
|
||||
for node_id in el.get('ids', ())]:
|
||||
target_node = nodes.target(ids=node_ids)
|
||||
self.set_source_info(target_node)
|
||||
return [self.indexnode, target_node]
|
||||
return [self.indexnode]
|
||||
return [self.indexnode, node]
|
||||
|
||||
|
||||
|
@ -3166,6 +3166,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
|
||||
option_spec: OptionSpec = {
|
||||
'noindexentry': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
'single-line-parameter-list': directives.flag,
|
||||
}
|
||||
|
||||
|
@ -7214,6 +7214,7 @@ class CPPObject(ObjectDescription[ASTDeclaration]):
|
||||
option_spec: OptionSpec = {
|
||||
'noindexentry': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
'tparam-line-spec': directives.flag,
|
||||
'single-line-parameter-list': directives.flag,
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ class JSObject(ObjectDescription[tuple[str, str]]):
|
||||
'noindex': directives.flag,
|
||||
'noindexentry': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
'single-line-parameter-list': directives.flag,
|
||||
}
|
||||
|
||||
@ -293,6 +294,7 @@ class JSModule(SphinxDirective):
|
||||
option_spec: OptionSpec = {
|
||||
'noindex': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
}
|
||||
|
||||
def run(self) -> list[Node]:
|
||||
@ -316,12 +318,13 @@ class JSModule(SphinxDirective):
|
||||
domain.note_object(mod_name, 'module', node_id,
|
||||
location=(self.env.docname, self.lineno))
|
||||
|
||||
target = nodes.target('', '', ids=[node_id], ismod=True)
|
||||
self.state.document.note_explicit_target(target)
|
||||
ret.append(target)
|
||||
# The node order is: index node first, then target node
|
||||
indextext = _('%s (module)') % mod_name
|
||||
inode = addnodes.index(entries=[('single', indextext, node_id, '', None)])
|
||||
ret.append(inode)
|
||||
target = nodes.target('', '', ids=[node_id], ismod=True)
|
||||
self.state.document.note_explicit_target(target)
|
||||
ret.append(target)
|
||||
ret.extend(content_node.children)
|
||||
return ret
|
||||
|
||||
|
@ -662,6 +662,7 @@ class PyObject(ObjectDescription[tuple[str, str]]):
|
||||
'noindex': directives.flag,
|
||||
'noindexentry': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
'single-line-parameter-list': directives.flag,
|
||||
'single-line-type-parameter-list': directives.flag,
|
||||
'module': directives.unchanged,
|
||||
@ -1262,6 +1263,7 @@ class PyModule(SphinxDirective):
|
||||
'synopsis': lambda x: x,
|
||||
'noindex': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
'deprecated': directives.flag,
|
||||
}
|
||||
|
||||
@ -1294,10 +1296,11 @@ class PyModule(SphinxDirective):
|
||||
|
||||
# the platform and synopsis aren't printed; in fact, they are only
|
||||
# used in the modindex currently
|
||||
ret.append(target)
|
||||
indextext = f'module; {modname}'
|
||||
inode = addnodes.index(entries=[('pair', indextext, node_id, '', None)])
|
||||
# The node order is: index node first, then target node.
|
||||
ret.append(inode)
|
||||
ret.append(target)
|
||||
ret.extend(content_node.children)
|
||||
return ret
|
||||
|
||||
|
@ -37,6 +37,7 @@ class ReSTMarkup(ObjectDescription[str]):
|
||||
'noindex': directives.flag,
|
||||
'noindexentry': directives.flag,
|
||||
'nocontentsentry': directives.flag,
|
||||
'no-typesetting': directives.flag,
|
||||
}
|
||||
|
||||
def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
|
||||
|
@ -414,6 +414,77 @@ class GlossarySorter(SphinxTransform):
|
||||
)
|
||||
|
||||
|
||||
class ReorderConsecutiveTargetAndIndexNodes(SphinxTransform):
|
||||
"""Index nodes interspersed between target nodes prevent other
|
||||
Transformations from combining those target nodes,
|
||||
e.g. ``PropagateTargets``. This transformation reorders them:
|
||||
|
||||
Given the following ``document`` as input::
|
||||
|
||||
<document>
|
||||
<target ids="id1" ...>
|
||||
<index entries="...1...">
|
||||
<target ids="id2" ...>
|
||||
<target ids="id3" ...>
|
||||
<index entries="...2...">
|
||||
<target ids="id4" ...>
|
||||
|
||||
The transformed result will be::
|
||||
|
||||
<document>
|
||||
<index entries="...1...">
|
||||
<index entries="...2...">
|
||||
<target ids="id1" ...>
|
||||
<target ids="id2" ...>
|
||||
<target ids="id3" ...>
|
||||
<target ids="id4" ...>
|
||||
"""
|
||||
|
||||
# This transform MUST run before ``PropagateTargets``.
|
||||
default_priority = 220
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
for target in self.document.findall(nodes.target):
|
||||
_reorder_index_target_nodes(target)
|
||||
|
||||
|
||||
def _reorder_index_target_nodes(start_node: nodes.target) -> None:
|
||||
"""Sort target and index nodes.
|
||||
|
||||
Find all consecutive target and index nodes starting from ``start_node``,
|
||||
and move all index nodes to before the first target node.
|
||||
"""
|
||||
nodes_to_reorder: list[nodes.target | addnodes.index] = []
|
||||
|
||||
# Note that we cannot use 'condition' to filter,
|
||||
# as we want *consecutive* target & index nodes.
|
||||
node: nodes.Node
|
||||
for node in start_node.findall(descend=False, siblings=True):
|
||||
if isinstance(node, (nodes.target, addnodes.index)):
|
||||
nodes_to_reorder.append(node)
|
||||
continue
|
||||
break # must be a consecutive run of target or index nodes
|
||||
|
||||
if len(nodes_to_reorder) < 2:
|
||||
return # Nothing to reorder
|
||||
|
||||
parent = nodes_to_reorder[0].parent
|
||||
if parent == nodes_to_reorder[-1].parent:
|
||||
first_idx = parent.index(nodes_to_reorder[0])
|
||||
last_idx = parent.index(nodes_to_reorder[-1])
|
||||
if first_idx + len(nodes_to_reorder) - 1 == last_idx:
|
||||
parent[first_idx:last_idx + 1] = sorted(nodes_to_reorder, key=_sort_key)
|
||||
|
||||
|
||||
def _sort_key(node: nodes.Node) -> int:
|
||||
# Must be a stable sort.
|
||||
if isinstance(node, addnodes.index):
|
||||
return 0
|
||||
if isinstance(node, nodes.target):
|
||||
return 1
|
||||
raise ValueError(f'_sort_key called with unexpected node type {type(node)!r}')
|
||||
|
||||
|
||||
def setup(app: Sphinx) -> dict[str, Any]:
|
||||
app.add_transform(ApplySourceWorkaround)
|
||||
app.add_transform(ExtraTranslatableNodes)
|
||||
@ -430,6 +501,7 @@ def setup(app: Sphinx) -> dict[str, Any]:
|
||||
app.add_transform(DoctreeReadEvent)
|
||||
app.add_transform(ManpageLink)
|
||||
app.add_transform(GlossarySorter)
|
||||
app.add_transform(ReorderConsecutiveTargetAndIndexNodes)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
108
tests/test_directives_no_typesetting.py
Normal file
108
tests/test_directives_no_typesetting.py
Normal file
@ -0,0 +1,108 @@
|
||||
"""Tests the directives"""
|
||||
|
||||
import pytest
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.testing import restructuredtext
|
||||
from sphinx.testing.util import assert_node
|
||||
|
||||
DOMAINS = [
|
||||
# directive, noindex, noindexentry, signature of f, signature of g, index entry of g
|
||||
('c:function', False, True, 'void f()', 'void g()', ('single', 'g (C function)', 'c.g', '', None)),
|
||||
('cpp:function', False, True, 'void f()', 'void g()', ('single', 'g (C++ function)', '_CPPv41gv', '', None)),
|
||||
('js:function', True, True, 'f()', 'g()', ('single', 'g() (built-in function)', 'g', '', None)),
|
||||
('py:function', True, True, 'f()', 'g()', ('pair', 'built-in function; g()', 'g', '', None)),
|
||||
('rst:directive', True, False, 'f', 'g', ('single', 'g (directive)', 'directive-g', '', None)),
|
||||
('cmdoption', True, False, 'f', 'g', ('pair', 'command line option; g', 'cmdoption-arg-g', '', None)),
|
||||
('envvar', True, False, 'f', 'g', ('single', 'environment variable; g', 'envvar-g', '', None)),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :no-typesetting:\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index, nodes.target))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting_twice(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'.. {directive}:: {sig_g}\n'
|
||||
f' :no-typesetting:\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
# Note that all index nodes come before the target nodes
|
||||
assert_node(doctree, (addnodes.index, addnodes.index, nodes.target, nodes.target))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting_noindex_orig(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
if not noindex:
|
||||
pytest.skip(f'{directive} does not support :noindex: option')
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :noindex:\n'
|
||||
f'.. {directive}:: {sig_g}\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index, addnodes.desc, addnodes.index, addnodes.desc))
|
||||
assert_node(doctree[2], addnodes.index, entries=[index_g])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting_noindex(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
if not noindex:
|
||||
pytest.skip(f'{directive} does not support :noindex: option')
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :noindex:\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'.. {directive}:: {sig_g}\n'
|
||||
f' :no-typesetting:\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index, addnodes.index, nodes.target))
|
||||
assert_node(doctree[0], addnodes.index, entries=[])
|
||||
assert_node(doctree[1], addnodes.index, entries=[index_g])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting_noindexentry(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
if not noindexentry:
|
||||
pytest.skip(f'{directive} does not support :noindexentry: option')
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :noindexentry:\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'.. {directive}:: {sig_g}\n'
|
||||
f' :no-typesetting:\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index, addnodes.index, nodes.target, nodes.target))
|
||||
assert_node(doctree[0], addnodes.index, entries=[])
|
||||
assert_node(doctree[1], addnodes.index, entries=[index_g])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting_code(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'.. {directive}:: {sig_g}\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'.. code::\n'
|
||||
f'\n'
|
||||
f' code\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
# Note that all index nodes come before the targets
|
||||
assert_node(doctree, (addnodes.index, addnodes.index, nodes.target, nodes.target, nodes.literal_block))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('directive', 'noindex', 'noindexentry', 'sig_f', 'sig_g', 'index_g'), DOMAINS)
|
||||
def test_object_description_no_typesetting_heading(app, directive, noindex, noindexentry, sig_f, sig_g, index_g):
|
||||
text = (f'.. {directive}:: {sig_f}\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'.. {directive}:: {sig_g}\n'
|
||||
f' :no-typesetting:\n'
|
||||
f'\n'
|
||||
f'Heading\n'
|
||||
f'=======\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
# Note that all index nodes come before the targets and the heading is floated before those.
|
||||
assert_node(doctree, (nodes.title, addnodes.index, addnodes.index, nodes.target, nodes.target))
|
@ -177,11 +177,11 @@ def test_get_full_qualified_name():
|
||||
def test_js_module(app):
|
||||
text = ".. js:module:: sphinx"
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (nodes.target,
|
||||
addnodes.index))
|
||||
assert_node(doctree[0], nodes.target, ids=["module-sphinx"])
|
||||
assert_node(doctree[1], addnodes.index,
|
||||
assert_node(doctree, (addnodes.index,
|
||||
nodes.target))
|
||||
assert_node(doctree[0], addnodes.index,
|
||||
entries=[("single", "sphinx (module)", "module-sphinx", "", None)])
|
||||
assert_node(doctree[1], nodes.target, ids=["module-sphinx"])
|
||||
|
||||
|
||||
def test_js_function(app):
|
||||
|
@ -660,9 +660,9 @@ def test_pydata(app):
|
||||
" :type: int\n")
|
||||
domain = app.env.get_domain('py')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (nodes.target,
|
||||
addnodes.index,
|
||||
assert_node(doctree, (addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
[desc, ([desc_signature, ([desc_addname, "example."],
|
||||
[desc_name, "var"],
|
||||
[desc_annotation, ([desc_sig_punctuation, ':'],
|
||||
@ -685,9 +685,9 @@ def test_pyfunction(app):
|
||||
[desc, ([desc_signature, ([desc_name, "func1"],
|
||||
[desc_parameterlist, ()])],
|
||||
[desc_content, ()])],
|
||||
addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
addnodes.index,
|
||||
addnodes.index,
|
||||
[desc, ([desc_signature, ([desc_annotation, ([desc_sig_keyword, 'async'],
|
||||
desc_sig_space)],
|
||||
[desc_addname, "example."],
|
||||
@ -696,9 +696,9 @@ def test_pyfunction(app):
|
||||
[desc_content, ()])]))
|
||||
assert_node(doctree[0], addnodes.index,
|
||||
entries=[('pair', 'built-in function; func1()', 'func1', '', None)])
|
||||
assert_node(doctree[3], addnodes.index,
|
||||
assert_node(doctree[2], addnodes.index,
|
||||
entries=[('pair', 'module; example', 'module-example', '', None)])
|
||||
assert_node(doctree[4], addnodes.index,
|
||||
assert_node(doctree[3], addnodes.index,
|
||||
entries=[('single', 'func2() (in module example)', 'example.func2', '', None)])
|
||||
|
||||
assert 'func1' in domain.objects
|
||||
@ -1043,9 +1043,9 @@ def test_info_field_list(app):
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
print(doctree)
|
||||
|
||||
assert_node(doctree, (nodes.target,
|
||||
addnodes.index,
|
||||
assert_node(doctree, (addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
[desc, ([desc_signature, ([desc_annotation, ("class", desc_sig_space)],
|
||||
[desc_addname, "example."],
|
||||
[desc_name, "Class"])],
|
||||
@ -1134,9 +1134,9 @@ def test_info_field_list_piped_type(app):
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
|
||||
assert_node(doctree,
|
||||
(nodes.target,
|
||||
addnodes.index,
|
||||
(addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
[desc, ([desc_signature, ([desc_annotation, ("class", desc_sig_space)],
|
||||
[desc_addname, "example."],
|
||||
[desc_name, "Class"])],
|
||||
@ -1168,9 +1168,9 @@ def test_info_field_list_Literal(app):
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
|
||||
assert_node(doctree,
|
||||
(nodes.target,
|
||||
addnodes.index,
|
||||
(addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
[desc, ([desc_signature, ([desc_annotation, ("class", desc_sig_space)],
|
||||
[desc_addname, "example."],
|
||||
[desc_name, "Class"])],
|
||||
|
96
tests/test_transforms_reorder_nodes.py
Normal file
96
tests/test_transforms_reorder_nodes.py
Normal file
@ -0,0 +1,96 @@
|
||||
"""Tests the transformations"""
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.testing import restructuredtext
|
||||
from sphinx.testing.util import assert_node
|
||||
|
||||
|
||||
def test_transforms_reorder_consecutive_target_and_index_nodes_preserve_order(app):
|
||||
text = ('.. index:: abc\n'
|
||||
'.. index:: def\n'
|
||||
'.. index:: ghi\n'
|
||||
'.. index:: jkl\n'
|
||||
'\n'
|
||||
'text\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index,
|
||||
addnodes.index,
|
||||
addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.paragraph))
|
||||
assert_node(doctree[0], addnodes.index, entries=[('single', 'abc', 'index-0', '', None)])
|
||||
assert_node(doctree[1], addnodes.index, entries=[('single', 'def', 'index-1', '', None)])
|
||||
assert_node(doctree[2], addnodes.index, entries=[('single', 'ghi', 'index-2', '', None)])
|
||||
assert_node(doctree[3], addnodes.index, entries=[('single', 'jkl', 'index-3', '', None)])
|
||||
assert_node(doctree[4], nodes.target, refid='index-0')
|
||||
assert_node(doctree[5], nodes.target, refid='index-1')
|
||||
assert_node(doctree[6], nodes.target, refid='index-2')
|
||||
assert_node(doctree[7], nodes.target, refid='index-3')
|
||||
# assert_node(doctree[8], nodes.paragraph)
|
||||
|
||||
|
||||
def test_transforms_reorder_consecutive_target_and_index_nodes_no_merge_across_other_nodes(app):
|
||||
text = ('.. index:: abc\n'
|
||||
'.. index:: def\n'
|
||||
'\n'
|
||||
'text\n'
|
||||
'\n'
|
||||
'.. index:: ghi\n'
|
||||
'.. index:: jkl\n'
|
||||
'\n'
|
||||
'text\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.paragraph,
|
||||
addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.paragraph))
|
||||
assert_node(doctree[0], addnodes.index, entries=[('single', 'abc', 'index-0', '', None)])
|
||||
assert_node(doctree[1], addnodes.index, entries=[('single', 'def', 'index-1', '', None)])
|
||||
assert_node(doctree[2], nodes.target, refid='index-0')
|
||||
assert_node(doctree[3], nodes.target, refid='index-1')
|
||||
# assert_node(doctree[4], nodes.paragraph)
|
||||
assert_node(doctree[5], addnodes.index, entries=[('single', 'ghi', 'index-2', '', None)])
|
||||
assert_node(doctree[6], addnodes.index, entries=[('single', 'jkl', 'index-3', '', None)])
|
||||
assert_node(doctree[7], nodes.target, refid='index-2')
|
||||
assert_node(doctree[8], nodes.target, refid='index-3')
|
||||
# assert_node(doctree[9], nodes.paragraph)
|
||||
|
||||
|
||||
def test_transforms_reorder_consecutive_target_and_index_nodes_merge_with_labels(app):
|
||||
text = ('.. _abc:\n'
|
||||
'.. index:: def\n'
|
||||
'.. _ghi:\n'
|
||||
'.. index:: jkl\n'
|
||||
'.. _mno:\n'
|
||||
'\n'
|
||||
'Heading\n'
|
||||
'=======\n')
|
||||
doctree = restructuredtext.parse(app, text)
|
||||
assert_node(doctree, (nodes.title,
|
||||
addnodes.index,
|
||||
addnodes.index,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.target,
|
||||
nodes.target))
|
||||
# assert_node(doctree[8], nodes.title)
|
||||
assert_node(doctree[1], addnodes.index, entries=[('single', 'def', 'index-0', '', None)])
|
||||
assert_node(doctree[2], addnodes.index, entries=[('single', 'jkl', 'index-1', '', None)])
|
||||
assert_node(doctree[3], nodes.target, refid='abc')
|
||||
assert_node(doctree[4], nodes.target, refid='index-0')
|
||||
assert_node(doctree[5], nodes.target, refid='ghi')
|
||||
assert_node(doctree[6], nodes.target, refid='index-1')
|
||||
assert_node(doctree[7], nodes.target, refid='mno')
|
Loading…
Reference in New Issue
Block a user