|
From: <mi...@us...> - 2026-07-14 13:31:54
|
Revision: 10381
http://sourceforge.net/p/docutils/code/10381
Author: milde
Date: 2026-07-14 13:31:29 +0000 (Tue, 14 Jul 2026)
Log Message:
-----------
"lazy IDs": Generate "implicit" section IDs only if required.
Do not load/run the `SectionIDs` transform.
Keep it so that components/applications that want IDs on all sections
can easily add it to their `get_transforms_spec()` method.
+ Links from the ToC and "self-links" use the same ID
("explicit" ID, if available).
+ Less "noise" in the output document.
Full backwards compatibility can be achieved with setting "legacy_ids".
Modified Paths:
--------------
trunk/docutils/HISTORY.rst
trunk/docutils/RELEASE-NOTES.rst
trunk/docutils/docs/api/transforms.rst
trunk/docutils/docs/user/config.rst
trunk/docutils/docutils/parsers/__init__.py
trunk/docutils/docutils/readers/standalone.py
trunk/docutils/docutils/transforms/parts.py
trunk/docutils/docutils/transforms/references.py
trunk/docutils/docutils/writers/html5_polyglot/__init__.py
trunk/docutils/test/data/help/docutils.rst
trunk/docutils/test/data/help/rst2html.rst
trunk/docutils/test/data/help/rst2latex.rst
trunk/docutils/test/functional/expected/length_units_html5.html
trunk/docutils/test/functional/expected/misc_rst_html5.html
trunk/docutils/test/functional/expected/standalone_rst_html5.html
trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt
trunk/docutils/test/functional/expected/standalone_rst_xetex.tex
trunk/docutils/test/functional/tests/length_units_html5.py
trunk/docutils/test/test_transforms/test_contents.py
trunk/docutils/test/test_transforms/test_hyperlinks.py
trunk/docutils/test/test_transforms/test_sectnum.py
Modified: trunk/docutils/HISTORY.rst
===================================================================
--- trunk/docutils/HISTORY.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/HISTORY.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -51,6 +51,7 @@
* docutils/parsers/__init__.py
- Remove `recommonmark` from `PARSER_ALIASES`.
+ - Rename command line option ``--matching-ids`` to ``--lazy-ids``.
* docutils/parsers/commonmark_wrapper.py
@@ -87,11 +88,17 @@
- Update `Reader.get_transforms()` to load the three transforms
obsoleting `references.DanglingReferences` (see below).
+ - Do not load `transforms.references.SectionIDs`.
* docutils/transforms/__init__.py
- Remove `Transformer.unknown_reference_resolvers`.
+* docutils/transforms/parts.py:
+
+ - `Contents.build_contents()`: ensure sections have an ID and prefer
+ IDs from external targets with "lazy IDs" (`legacy_ids`_ False).
+
* docutils/transforms/references.py
- `IndirectHyperlinks.resolve_indirect_target()` no longer calls
@@ -100,6 +107,8 @@
and `ReportUnreferencedLinks` obsolete `DanglingReferences`.
- Add INFO system_message if a <target> cannot be propagated
to the next node.
+ - support "lazy IDs": Handle hyperlink targets without ID;
+ if required, generate and set one.
* docutils/transforms/universal.py
@@ -123,6 +132,7 @@
problems with other elements using "topic" as class value (e.g. a
docinfo item "topic" in Enhancement Reports).
- More robust handling of figure captions.
+ - Support "lazy IDs": ensure sections have an ID when adding a self-link.
* docutils/writers/latex2e/__init__.py
Modified: trunk/docutils/RELEASE-NOTES.rst
===================================================================
--- trunk/docutils/RELEASE-NOTES.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/RELEASE-NOTES.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -220,6 +220,7 @@
- The legacy_column_widths_ setting now defaults to False.
- The initial_header_level_ setting default for the HTML5 writer
changed to "auto".
+ - Rename command line option ``--matching-ids`` to ``--lazy-ids``.
Command line interface:
- Option ``-o`` sets the `output file path <output_path_>`__
@@ -227,8 +228,14 @@
- Drop the ``<destination>`` positional argument.
Use ``-o <destination>`` or output redirection.
+standalone reader:
+ - Do not load the `SectionIDs` transform.
+
rST parser:
- Warn if a `"figure"`_ directive is missing both caption and legend.
+ - Generate identifiers for implicit targets (mainly sections) only if
+ there is a cross-link to the target [#cross-links]_ and no "explicit"
+ identifier (unless legacy_ids_ is True).
HTML5 writer:
- Use normal font size and colour for informal titles of type "rubric".
@@ -285,6 +292,9 @@
`writers.latex2e.SortableDict`
Not used and deprecated since Docutils 0.22.
+.. [#cross-links] This includes links from the table of contents_ and
+ "`section self-links <section_self_link_>`_" added by the HTML5
+ writer.
Release 0.23 (2026-05-27)
=========================
Modified: trunk/docutils/docs/api/transforms.rst
===================================================================
--- trunk/docutils/docs/api/transforms.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docs/api/transforms.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -57,7 +57,7 @@
references_.Substitutions standalone_ (r), pep_ (r) _`220`
-references_.SectionIDs standalone_ (r), pep_ (r) _`240`
+references_.SectionIDs *not used* _`240`
references_.PropagateTargets standalone_ (r), pep_ (r) _`260`
Modified: trunk/docutils/docs/user/config.rst
===================================================================
--- trunk/docutils/docs/user/config.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docs/user/config.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -798,16 +798,38 @@
Keep element identifiers_ compatible to Docutils ≤ 0.22.
-In case of a name conflict with an `implicit target`_ (section heading),
-identifiers_ may have a disambiguating number added to the normalized
-`reference name`_.
+If "legacy_ids" is False or with the command line option ``--lazy-ids``,
+the generation of identifiers_ from the `reference names`_ of
+`implicit targets`_ is done after parsing is complete and only
+if required by an internal cross-link [#cross-link]_.
+An existing identifier from an `explicit target`_ is re-used instead of
+generating an additional identifier for the "implicit" reference name.
-:Default: True; will change to False in Docutils 2.0.
-:Options: ``--legacy-ids``, ``--matching-ids``.
+* Less "noise" in generated output documents.
+* Less cluttered identifier namespace: `explicit targets`_ have a better
+ chance to get an identifier_ matching their `reference name`_. [#]_
-New in Docutils 0.23. Provisional.
+.. caution:: Changing this setting may alter IDs in the output document
+ and hence break incoming "deep" hyperlinks that use "implicit"
+ identifiers in their `URI fragment`_.
+:Default: True (will change to False in Docutils 2.0).
+:Options: ``--legacy-ids``,
+ ``--lazy-ids`` (name changed in Docutils 1.0).
+New in Docutils 0.23. Provisional.
+
+.. [#cross-link]
+ Internal cross-links include links from `hyperlink references`_,
+ the `table of contents`_, and "`self-links <section_self_link_>`_"
+ added by the HTML5 writer.
+.. [#]
+ Due to the `identifier normalization`_, different `reference names`_
+ may compete for the same identifier_, e.g. the reference names
+ ``"legacy ids"`` and ``"legacy-ids"`` would get the
+ identifiers ``"legacy-ids"`` and ``"legacy-ids-1"``.
+
+
raw_enabled
-----------
@@ -2634,6 +2656,8 @@
.. _"code": ../ref/rst/directives.html#code
.. _"csv-table": ../ref/rst/directives.html#csv-table
.. _"figure": ../ref/rst/directives.html#figure
+.. _identifier normalization:
+ ../ref/rst/directives.html#identifier-normalization
.. _images:
.. _"image": ../ref/rst/directives.html#image
.. _"include": ../ref/rst/directives.html#include
@@ -2662,12 +2686,15 @@
.. _citations: ../ref/rst/restructuredtext.html#citations
.. _document title: ../ref/rst/restructuredtext.html#document-title
.. _enumerated lists: ../ref/rst/restructuredtext.html#enumerated-lists
-.. _explicit target: ../ref/rst/restructuredtext.html#explicit-hyperlink-targets
+.. _explicit target:
+.. _explicit targets: ../ref/rst/restructuredtext.html#explicit-hyperlink-targets
+.. _explicit internal target: ../ref/rst/restructuredtext.html#internal-hyperlink-targets
.. _field lists: ../ref/rst/restructuredtext.html#field-lists
.. _field names: ../ref/rst/restructuredtext.html#field-names
.. _footnotes: ../ref/rst/restructuredtext.html#footnotes
.. _footnote references: ../ref/rst/restructuredtext.html#footnote-references
.. _hyperlink references: ../ref/rst/restructuredtext.html#hyperlink-references
+.. _implicit hyperlink targets:
.. _implicit target:
.. _implicit targets: ../ref/rst/restructuredtext.html#implicit-hyperlink-targets
.. _interpreted text role: ../ref/rst/restructuredtext.html#interpreted-text
@@ -2675,6 +2702,7 @@
../ref/rst/restructuredtext.html#inline-markup-recognition-rules
.. _literal blocks: ../ref/rst/restructuredtext.html#literal-blocks
.. _option lists: ../ref/rst/restructuredtext.html#option-lists
+.. _sections: ../ref/rst/restructuredtext.html#sections
.. _tables: ../ref/rst/restructuredtext.html#tables
.. _Docutils HTML writers: html.html
@@ -2701,3 +2729,5 @@
.. _standard encodings:
https://docs.python.org/3/library/codecs.html#standard-encodings
.. _inspecting_codecs: https://codeberg.org/milde/inspecting-codecs
+.. _URI fragment:
+ https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Fragment
Modified: trunk/docutils/docutils/parsers/__init__.py
===================================================================
--- trunk/docutils/docutils/parsers/__init__.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docutils/parsers/__init__.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -47,12 +47,12 @@
['--line-length-limit'],
{'metavar': '<length>', 'type': 'int', 'default': 10_000,
'validator': frontend.validate_nonnegative_int}),
- ('Keep identifiers backwards compatible. (default)',
+ ('Keep IDs backwards compatible. (default)',
['--legacy-ids'],
{'action': 'store_true', 'default': True,
'validator': frontend.validate_boolean}),
- ('Explicit targets use identifiers matching the reference name.',
- ['--matching-ids'],
+ ('Generate IDs for implicit targets only if required.',
+ ['--lazy-ids'],
{'dest': 'legacy_ids', 'action': 'store_false'}),
('Validate the document tree after parsing.',
['--validate'],
Modified: trunk/docutils/docutils/readers/standalone.py
===================================================================
--- trunk/docutils/docutils/readers/standalone.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docutils/readers/standalone.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -56,7 +56,6 @@
def get_transforms(self) -> list[type[Transform]]:
return super().get_transforms() + [
references.Substitutions,
- references.SectionIDs,
references.PropagateTargets,
frontmatter.DocTitle,
frontmatter.DocInfo,
Modified: trunk/docutils/docutils/transforms/parts.py
===================================================================
--- trunk/docutils/docutils/transforms/parts.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docutils/transforms/parts.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -118,12 +118,16 @@
sections = [sect for sect in node if isinstance(sect, nodes.section)]
entries = []
depth = self.startnode.details.get('depth', sys.maxsize)
+ legacy_ids = getattr(self.document.settings, "legacy_ids", True)
for section in sections:
title = section[0]
auto = title.get('auto') # May be set by SectNum.
entrytext = self.copy_and_filter(title)
- reference = nodes.reference('', '', refid=section['ids'][0],
- *entrytext)
+ if legacy_ids: # get first (backwards compatible)
+ sect_id = section['ids'][0]
+ else: # ensure there is an ID, get last
+ sect_id = self.document.set_id(section)
+ reference = nodes.reference('', '', refid=sect_id, *entrytext)
ref_id = self.document.set_id(reference,
suggested_prefix='toc-entry')
entry = nodes.paragraph('', '', reference)
Modified: trunk/docutils/docutils/transforms/references.py
===================================================================
--- trunk/docutils/docutils/transforms/references.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docutils/transforms/references.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -20,19 +20,18 @@
"""
Add identifiers to sections.
- If the "legacy_ids" configuration setting is False, the rST parser
- does not generate identifiers for implicit targets (e.g. sections)
- in order to give explicit targets preferential access to identifiers
- matching their reference name.
+ Since Docutils 0.23, the rST parser does not generate identifiers for
+ implicit targets (e.g. sections) unless the "legacy_ids" configuration
+ setting is True.
- However, the `parts.Contents` transform and most writers
- expect sections to have an identifier, so this transform adds them.
+ Components that expect all sections to have an identifier can either
+ set "legacy_ids" or load this transform to add them.
"""
default_priority = 240
def apply(self) -> None:
if getattr(self.document.settings, "legacy_ids", True):
- return
+ return # IDs already generated by parser
for node in self.document.findall(nodes.section):
self.document.set_id(node)
@@ -89,8 +88,8 @@
next_node.expect_referenced_by_name = {}
if not hasattr(next_node, 'expect_referenced_by_id'):
next_node.expect_referenced_by_id = {}
+ # Update mappings:
for id in target['ids']:
- # Update IDs to node mapping.
self.document.ids[id] = next_node
# If next_node is referenced by id ``id``, this
# target shall be marked as referenced.
@@ -883,16 +882,21 @@
nodes.citation_reference)):
if node.resolved or 'refname' not in node:
continue
- identifier = self.document.nameids.get(node['refname'])
- if identifier:
- # target found, set refid
- node['refid'] = identifier
- self.document.ids[identifier].note_referenced_by(id=identifier)
- # If a transform is able to resolve the reference,
- # it should # also remove the 'refname' attribute and
- # mark the node as resolved:
- del node['refname']
- node.resolved = True
+ refname = node['refname']
+ target = self.document.names.get(refname)
+ if target is None: # "refname" is unknown or duplicate
+ continue
+ # target found, set refid
+ refid = self.document.nameids.get(refname)
+ if refid:
+ target.note_referenced_by(id=refid)
+ else:
+ refid = self.document.set_id(target)
+ target.note_referenced_by(name=refname)
+ node['refid'] = refid
+ # cleanup
+ del node['refname']
+ node.resolved = True
class CitationReferences(Transform):
Modified: trunk/docutils/docutils/writers/html5_polyglot/__init__.py
===================================================================
--- trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/docutils/writers/html5_polyglot/__init__.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -347,6 +347,11 @@
# use the new HTML5 element <section>
def visit_section(self, node) -> None:
self.section_level += 1
+ # ensure the element has an ID if we want to add a self-link:
+ if (getattr(self.settings, 'section_self_link', None)
+ and not getattr(self.settings, 'legacy_ids', None)
+ and 'system-messages' not in node['classes']):
+ node.document.set_id(node)
self.body.append(self.starttag(node, 'section'))
def depart_section(self, node) -> None:
Modified: trunk/docutils/test/data/help/docutils.rst
===================================================================
--- trunk/docutils/test/data/help/docutils.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/data/help/docutils.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -89,9 +89,8 @@
--line-length-limit=<length>
Maximal number of characters in an input line.
(default 10 000)
---legacy-ids Keep identifiers backwards compatible. (default)
---matching-ids Explicit targets use identifiers matching the
- reference name.
+--legacy-ids Keep IDs backwards compatible. (default)
+--lazy-ids Generate IDs for implicit targets only if required.
--validate Validate the document tree after parsing.
--no-validation Do not validate the document tree. (default)
Modified: trunk/docutils/test/data/help/rst2html.rst
===================================================================
--- trunk/docutils/test/data/help/rst2html.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/data/help/rst2html.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -90,9 +90,8 @@
--line-length-limit=<length>
Maximal number of characters in an input line.
(default 10 000)
---legacy-ids Keep identifiers backwards compatible. (default)
---matching-ids Explicit targets use identifiers matching the
- reference name.
+--legacy-ids Keep IDs backwards compatible. (default)
+--lazy-ids Generate IDs for implicit targets only if required.
--validate Validate the document tree after parsing.
--no-validation Do not validate the document tree. (default)
Modified: trunk/docutils/test/data/help/rst2latex.rst
===================================================================
--- trunk/docutils/test/data/help/rst2latex.rst 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/data/help/rst2latex.rst 2026-07-14 13:31:29 UTC (rev 10381)
@@ -90,9 +90,8 @@
--line-length-limit=<length>
Maximal number of characters in an input line.
(default 10 000)
---legacy-ids Keep identifiers backwards compatible. (default)
---matching-ids Explicit targets use identifiers matching the
- reference name.
+--legacy-ids Keep IDs backwards compatible. (default)
+--lazy-ids Generate IDs for implicit targets only if required.
--validate Validate the document tree after parsing.
--no-validation Do not validate the document tree. (default)
Modified: trunk/docutils/test/functional/expected/length_units_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/length_units_html5.html 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/functional/expected/length_units_html5.html 2026-07-14 13:31:29 UTC (rev 10381)
@@ -9,10 +9,10 @@
<link rel="stylesheet" href="../input/data/plain.css" type="text/css" />
</head>
<body>
-<main id="test-length-specifications">
+<main>
<h1 class="title">Test length specifications</h1>
-<section id="images-and-figures">
+<section>
<h2>Images and Figures</h2>
<figure>
<img alt="blue square" height="32" src="../input/data/blue%20square.png" width="32" />
@@ -129,13 +129,13 @@
</figcaption>
</figure>
</section>
-<section id="ch-em-and-rem-test1ch-test1em-test1rem">
+<section>
<h2>ch, em, and rem: <img alt="test1ch" src="../input/data/blue%20square.png" style="height: 1ch;" /> <img alt="test1em" src="../input/data/blue%20square.png" style="height: 1em;" /> <img alt="test1rem" src="../input/data/blue%20square.png" style="height: 1rem;" /></h2>
<p>Image height 1ch, 1em, and 1rem: <img alt="test1ch" src="../input/data/blue%20square.png" style="height: 1ch;" /> <img alt="test1em" src="../input/data/blue%20square.png" style="height: 1em;" /> <img alt="test1rem" src="../input/data/blue%20square.png" style="height: 1rem;" /></p>
<p>The units "em" and "ch" change with the current font size.
The unit "rem" is tied to the document root fontsize.</p>
</section>
-<section id="tables">
+<section>
<h2>Tables</h2>
<table>
<tbody>
Modified: trunk/docutils/test/functional/expected/misc_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/misc_rst_html5.html 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/functional/expected/misc_rst_html5.html 2026-07-14 13:31:29 UTC (rev 10381)
@@ -9,7 +9,7 @@
<link rel="stylesheet" href="../input/data/responsive.css" type="text/css" />
</head>
<body class="with-toc">
-<main id="additional-tests-with-html-5">
+<main>
<h1 class="title">Additional tests with HTML 5</h1>
<nav class="contents" id="contents" role="doc-toc">
Modified: trunk/docutils/test/functional/expected/standalone_rst_html5.html
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_html5.html 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/functional/expected/standalone_rst_html5.html 2026-07-14 13:31:29 UTC (rev 10381)
@@ -21,10 +21,9 @@
<header>
<p>Document header</p>
</header>
-<main id="restructuredtext-test-document">
-<span id="doctitle"></span>
+<main id="doctitle">
<h1 class="title">reStructuredText Test Document</h1>
-<p class="subtitle" id="examples-of-syntax-constructs"><span id="subtitle"></span>Examples of Syntax Constructs</p>
+<p class="subtitle" id="subtitle">Examples of Syntax Constructs</p>
<dl class="docinfo">
<dt class="author">Author<span class="colon">:</span></dt>
<dd class="author"><p>David Goodger</p></dd>
@@ -109,7 +108,7 @@
<li><p><a class="reference internal" href="#doctest-blocks" id="toc-entry-16"><span class="sectnum">2.10 </span>Doctest Blocks</a></p></li>
<li><p><a class="reference internal" href="#footnotes" id="toc-entry-17"><span class="sectnum">2.11 </span>Footnotes</a></p></li>
<li><p><a class="reference internal" href="#citations" id="toc-entry-18"><span class="sectnum">2.12 </span>Citations</a></p></li>
-<li><p><a class="reference internal" href="#targets" id="toc-entry-19"><span class="sectnum">2.13 </span>Targets</a></p>
+<li><p><a class="reference internal" href="#another-target" id="toc-entry-19"><span class="sectnum">2.13 </span>Targets</a></p>
<ul class="auto-toc">
<li><p><a class="reference internal" href="#duplicate-target-names-1" id="toc-entry-20"><span class="sectnum">2.13.1 </span>Duplicate Target Names</a></p></li>
<li><p><a class="reference internal" href="#duplicate-target-names-2" id="toc-entry-21"><span class="sectnum">2.13.2 </span>Duplicate Target Names</a></p></li>
@@ -165,7 +164,7 @@
<h2><a class="toc-backref" href="#toc-entry-1" role="doc-backlink"><span class="sectnum">1 </span>Structural Elements</a><a class="self-link" title="link to this section" href="#structural-elements"></a></h2>
<section id="section-title">
<h3><a class="toc-backref" href="#toc-entry-2" role="doc-backlink"><span class="sectnum">1.1 </span>Section Title</a><a class="self-link" title="link to this section" href="#section-title"></a></h3>
-<p class="section-subtitle" id="section-subtitle">Section Subtitle</p>
+<p class="section-subtitle">Section Subtitle</p>
<p>Lone subsections are converted to a section subtitle by a transform
activated with the <span class="docutils literal"><span class="pre">--section-subtitles</span></span> command line option or the
<span class="docutils literal"><span class="pre">sectsubtitle-xform</span></span> configuration value.</p>
@@ -198,7 +197,7 @@
<a class="brackets" href="#label" id="footnote-reference-3" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>, or symbolic <a class="brackets" href="#footnote-3" id="footnote-reference-4" role="doc-noteref"><span class="fn-bracket">[</span>*<span class="fn-bracket">]</span></a>), citation references (see <a class="citation-reference" href="#cit2002" id="citation-reference-1" role="doc-biblioref">[CIT2002]</a>),
substitution references (<img alt="EXAMPLE" src="../../../docs/user/rst/images/biohazard.png" /> &
a <em>trimmed heart</em> <span class="docutils literal">(U+2665):</span>♥), and <span class="target" id="inline-hyperlink-targets">inline hyperlink targets</span>
-(see <a class="reference internal" href="#targets">Targets</a> below for a reference back to here). Character-level
+(see <a class="reference internal" href="#another-target">Targets</a> below for a reference back to here). Character-level
inline markup is also possible (although exceedingly ugly!) in <em>re</em><span class="docutils literal">Structured</span><em>Text</em>. Problems are indicated by <a href="#system-message-1"><span class="problematic" id="problematic-1">|problematic|</span></a> text
(generated by processing errors; this one is intentional). Here is a
reference to the <a class="reference internal" href="#doctitle">doctitle</a> and the <a class="reference internal" href="#subtitle">subtitle</a>.</p>
@@ -530,18 +529,17 @@
<p>Here's a reference to the above, <a class="citation-reference" href="#cit2002" id="citation-reference-2" role="doc-biblioref">[CIT2002]</a>, and a <a href="#system-message-3"><span class="problematic" id="citation-reference-3">[nonexistent]_</span></a>
citation.</p>
</section>
-<section id="targets">
-<span id="another-target"></span>
+<section id="another-target">
<h3><a class="toc-backref" href="#toc-entry-19" role="doc-backlink"><span class="sectnum">2.13 </span>Targets</a><a class="self-link" title="link to this section" href="#another-target"></a></h3>
<p id="example">This paragraph is pointed to by the explicit "example" target. A
reference can be found under <a class="reference internal" href="#inline-markup">Inline Markup</a>, above. <a class="reference internal" href="#inline-hyperlink-targets">Inline
hyperlink targets</a> are also possible.</p>
<p>Section headers are implicit targets, referred to by name. See
-<a class="reference internal" href="#targets">Targets</a>, which is a subsection of <a class="reference internal" href="#body-elements">Body Elements</a>.</p>
+<a class="reference internal" href="#another-target">Targets</a>, which is a subsection of <a class="reference internal" href="#body-elements">Body Elements</a>.</p>
<p>Explicit external targets are interpolated into references such as
"<a class="reference external" href="http://www.python.org/">Python</a> <a class="brackets" href="#footnote-7" id="footnote-reference-19" role="doc-noteref"><span class="fn-bracket">[</span>7<span class="fn-bracket">]</span></a>".</p>
-<p>Targets may be indirect and anonymous. Thus <a class="reference internal" href="#targets">this phrase</a> may also
-refer to the <a class="reference internal" href="#targets">Targets</a> section.</p>
+<p>Targets may be indirect and anonymous. Thus <a class="reference internal" href="#another-target">this phrase</a> may also
+refer to the <a class="reference internal" href="#another-target">Targets</a> section.</p>
<p>Here's a <a href="#system-message-4"><span class="problematic" id="problematic-2">`hyperlink reference without a target`_</span></a>, which generates an
error.</p>
<section id="duplicate-target-names-1">
Modified: trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/functional/expected/standalone_rst_pseudoxml.txt 2026-07-14 13:31:29 UTC (rev 10381)
@@ -1,7 +1,7 @@
-<document ids="restructuredtext-test-document doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_pseudoxml.rst" title="reStructuredText Test Document">
+<document ids="doctitle" names="restructuredtext\ test\ document doctitle" source="functional/input/standalone_rst_pseudoxml.rst" title="reStructuredText Test Document">
<title>
reStructuredText Test Document
- <subtitle ids="examples-of-syntax-constructs subtitle" names="examples\ of\ syntax\ constructs subtitle">
+ <subtitle ids="subtitle" names="examples\ of\ syntax\ constructs subtitle">
Examples of Syntax Constructs
<meta content="reStructuredText, test, parser" name="keywords">
<meta content="A test document, containing at least one example of each reStructuredText construct." lang="en" name="description">
@@ -204,7 +204,7 @@
Citations
<list_item>
<paragraph>
- <reference ids="toc-entry-19" refid="targets">
+ <reference ids="toc-entry-19" refid="another-target">
<generated classes="sectnum">
2.13
Targets
@@ -358,7 +358,7 @@
<generated classes="sectnum">
1.1
Section Title
- <subtitle ids="section-subtitle" names="section\ subtitle">
+ <subtitle names="section\ subtitle">
Section Subtitle
<paragraph>
Lone subsections are converted to a section subtitle by a transform
@@ -475,7 +475,7 @@
inline hyperlink targets
(see
- <reference refid="targets">
+ <reference refid="another-target">
Targets
below for a reference back to here). Character-level
inline markup is also possible (although exceedingly ugly!) in
@@ -1109,7 +1109,7 @@
citation.
<target refid="another-target">
- <section ids="targets another-target" names="targets another\ target">
+ <section ids="another-target" names="targets another\ target">
<title auto="1" refid="toc-entry-19">
<generated classes="sectnum">
2.13
@@ -1127,7 +1127,7 @@
are also possible.
<paragraph>
Section headers are implicit targets, referred to by name. See
- <reference refid="targets">
+ <reference refid="another-target">
Targets
, which is a subsection of
<reference refid="body-elements">
@@ -1145,14 +1145,14 @@
<target ids="python" names="python" refuri="http://www.python.org/">
<paragraph>
Targets may be indirect and anonymous. Thus
- <reference anonymous="1" refid="targets">
+ <reference anonymous="1" refid="another-target">
this phrase
may also
refer to the
- <reference refid="targets">
+ <reference refid="another-target">
Targets
section.
- <target anonymous="1" ids="target-4" refid="targets">
+ <target anonymous="1" ids="target-4" refid="another-target">
<paragraph>
Here's a
<problematic ids="problematic-2" refid="system-message-4">
@@ -2417,9 +2417,6 @@
<system_message level="1" line="159" source="functional/input/data/standard.rst" type="INFO">
<paragraph>
Hyperlink target "target" is not referenced.
- <system_message level="1" line="404" source="functional/input/data/standard.rst" type="INFO">
- <paragraph>
- Hyperlink target "another-target" is not referenced.
<system_message level="1" line="474" source="functional/input/data/standard.rst" type="INFO">
<paragraph>
Hyperlink target "image-target-1" is not referenced.
Modified: trunk/docutils/test/functional/expected/standalone_rst_xetex.tex
===================================================================
--- trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2026-07-14 13:31:29 UTC (rev 10381)
@@ -188,7 +188,7 @@
\item \hyperref[citations]{2.12 Citations}
-\item \hyperref[targets]{2.13 Targets}
+\item \hyperref[another-target]{2.13 Targets}
\begin{DUclass}{auto-toc}
\begin{itemize}
@@ -325,7 +325,7 @@
substitution references (\includegraphics{../../../docs/user/rst/images/biohazard.png} \&
a \emph{trimmed heart} \texttt{(U+2665):}♥), and %
\phantomsection\label{inline-hyperlink-targets}inline hyperlink targets
-(see \hyperref[targets]{Targets} below for a reference back to here). Character-level
+(see \hyperref[another-target]{Targets} below for a reference back to here). Character-level
inline markup is also possible (although exceedingly ugly!) in \emph{re}\texttt{Structured}\emph{Text}. Problems are indicated by %
\raisebox{1em}{\hypertarget{problematic-1}{}}\hyperlink{system-message-1}{\textbf{\color{red}|problematic|}} text
(generated by processing errors; this one is intentional). Here is a
@@ -739,7 +739,6 @@
\subsection{2.13 Targets%
- \label{targets}%
\label{another-target}%
}
@@ -749,13 +748,13 @@
hyperlink targets} are also possible.
Section headers are implicit targets, referred to by name. See
-\hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}.
+\hyperref[another-target]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}.
Explicit external targets are interpolated into references such as
“\href{http://www.python.org/}{Python}\DUfootnotemark{footnote-reference-11}{footnote-6}{5}”.
-Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also
-refer to the \hyperref[targets]{Targets} section.
+Targets may be indirect and anonymous. Thus \hyperref[another-target]{this phrase} may also
+refer to the \hyperref[another-target]{Targets} section.
Here’s a %
\raisebox{1em}{\hypertarget{problematic-2}{}}\hyperlink{system-message-4}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an
Modified: trunk/docutils/test/functional/tests/length_units_html5.py
===================================================================
--- trunk/docutils/test/functional/tests/length_units_html5.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/functional/tests/length_units_html5.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -16,4 +16,5 @@
# location of stylesheets (relative to ``docutils/test/``)
'stylesheet_dirs': ('functional/input/data', ),
'section_self_link': False,
+ 'legacy_ids': False,
}
Modified: trunk/docutils/test/test_transforms/test_contents.py
===================================================================
--- trunk/docutils/test/test_transforms/test_contents.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/test_transforms/test_contents.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -20,7 +20,7 @@
from docutils.frontend import get_default_settings
from docutils.parsers.rst import Parser
-from docutils.transforms.references import SectionIDs, Substitutions
+from docutils.transforms.references import Substitutions
from docutils.transforms.universal import TestMessages
from docutils.utils import new_document
@@ -46,7 +46,7 @@
totest = {}
-totest['tables_of_contents'] = ((SectionIDs, Substitutions,), [
+totest['tables_of_contents'] = ((Substitutions,), [
["""\
.. contents::
Modified: trunk/docutils/test/test_transforms/test_hyperlinks.py
===================================================================
--- trunk/docutils/test/test_transforms/test_hyperlinks.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/test_transforms/test_hyperlinks.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -20,7 +20,7 @@
from docutils.frontend import get_default_settings
from docutils.parsers.rst import Parser
from docutils.transforms.references import (
- SectionIDs, PropagateTargets, AnonymousHyperlinks, IndirectHyperlinks,
+ PropagateTargets, AnonymousHyperlinks, IndirectHyperlinks,
ExternalTargets, InternalTargets, DanglingReferences, MatchReferences,
ReportDanglingReferences, ReportUnreferencedTargets)
from docutils.transforms.universal import TestMessages
@@ -33,7 +33,7 @@
transforms = (PropagateTargets, AnonymousHyperlinks, IndirectHyperlinks,
ExternalTargets, InternalTargets, MatchReferences,
ReportDanglingReferences, ReportUnreferencedTargets,
- SectionIDs, TestMessages)
+ TestMessages)
def test_transforms(self):
parser = Parser()
@@ -594,7 +594,7 @@
"""],
])
-totest['hyperlinks legacy'] = ({'legacy_ids': True}, [
+totest['explicit hyperlinks legacy'] = ({'legacy_ids': True}, [
["""\
.. _internal hyperlink:
@@ -1036,6 +1036,58 @@
to an image with target (sic!).
"""],
["""\
+Unknown reference_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Unknown \n\
+ <problematic ids="problematic-1" refid="system-message-1">
+ reference_
+ .
+ <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Unknown target name: "reference".
+"""],
+["""\
+Duplicate manual footnote labels, with reference ([1]_):
+
+.. [1] Footnote.
+
+.. [1] Footnote.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate manual footnote labels, with reference (
+ <problematic ids="footnote-reference-1" refid="system-message-1">
+ [1]_
+ ):
+ <footnote dupnames="1" ids="footnote-1">
+ <label>
+ 1
+ <paragraph>
+ Footnote.
+ <footnote dupnames="1" ids="footnote-2">
+ <label>
+ 1
+ <system_message backrefs="footnote-2" level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "1".
+ <paragraph>
+ Footnote.
+ <system_message backrefs="footnote-reference-1" ids="system-message-1" level="3" line="1" source="test data" type="ERROR">
+ <paragraph>
+ Duplicate target name, cannot be used as a unique reference: "1".
+"""],
+])
+
+totest['explicit hyperlinks'] = ({'legacy_ids': False},
+ # all samples compile as before
+ totest['explicit hyperlinks legacy'][1])
+
+totest['implicit hyperlinks legacy'] = ({'legacy_ids': True}, [
+["""\
.. contents:: Table of Contents
.. _indirect reference to the table of contents: `table of contents`_
@@ -1109,51 +1161,6 @@
Title
"""],
["""\
-Unknown reference_.
-""",
-"""\
-<document source="test data">
- <paragraph>
- Unknown \n\
- <problematic ids="problematic-1" refid="system-message-1">
- reference_
- .
- <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="1" source="test data" type="ERROR">
- <paragraph>
- Unknown target name: "reference".
-"""],
-["""\
-Duplicate manual footnote labels, with reference ([1]_):
-
-.. [1] Footnote.
-
-.. [1] Footnote.
-""",
-"""\
-<document source="test data">
- <paragraph>
- Duplicate manual footnote labels, with reference (
- <problematic ids="footnote-reference-1" refid="system-message-1">
- [1]_
- ):
- <footnote dupnames="1" ids="footnote-1">
- <label>
- 1
- <paragraph>
- Footnote.
- <footnote dupnames="1" ids="footnote-2">
- <label>
- 1
- <system_message backrefs="footnote-2" level="2" line="5" source="test data" type="WARNING">
- <paragraph>
- Duplicate explicit target name: "1".
- <paragraph>
- Footnote.
- <system_message backrefs="footnote-reference-1" ids="system-message-1" level="3" line="1" source="test data" type="ERROR">
- <paragraph>
- Duplicate target name, cannot be used as a unique reference: "1".
-"""],
-["""\
An explicit target _`foo` overrides a homonymous implicit target.
foo
@@ -1213,10 +1220,84 @@
"""],
])
-totest['hyperlinks'] = ({'legacy_ids': False},
- # all but the last sample compile as before
- totest['hyperlinks legacy'][1][:-1] + [
+totest['implicit hyperlinks'] = ({'legacy_ids': False}, [
["""\
+.. contents:: Table of Contents
+.. _indirect reference to the table of contents: `table of contents`_
+
+Section
+=======
+
+Testing an `indirect reference to the table of contents`_.
+""",
+"""\
+<document source="test data">
+ <topic classes="contents" ids="table-of-contents" names="table\\ of\\ contents">
+ <title>
+ Table of Contents
+ <bullet_list>
+ <list_item>
+ <paragraph>
+ <reference ids="toc-entry-1" refid="section">
+ Section
+ <target ids="indirect-reference-to-the-table-of-contents" names="indirect\\ reference\\ to\\ the\\ table\\ of\\ contents" refid="table-of-contents">
+ <section ids="section" names="section">
+ <title refid="toc-entry-1">
+ Section
+ <paragraph>
+ Testing an \n\
+ <reference refid="table-of-contents">
+ indirect reference to the table of contents
+ .
+"""],
+["""\
+.. _explicit target:
+
+Title
+-----
+
+References to the section (title_) use the ID from the `explicit target`_.
+""",
+"""\
+<document source="test data">
+ <target refid="explicit-target">
+ <section ids="explicit-target" names="title explicit\\ target">
+ <title>
+ Title
+ <paragraph>
+ References to the section (
+ <reference refid="explicit-target">
+ title
+ ) use the ID from the \n\
+ <reference refid="explicit-target">
+ explicit target
+ .
+"""],
+["""\
+target1_ should refer to target2_, not the Title.
+
+.. _target1:
+.. _target2: URI
+
+Title
+=====
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ <reference refuri="URI">
+ target1
+ should refer to \n\
+ <reference refuri="URI">
+ target2
+ , not the Title.
+ <target refid="target1">
+ <target ids="target2 target1" names="target2 target1" refuri="URI">
+ <section names="title">
+ <title>
+ Title
+"""],
+["""\
foo
---
@@ -1229,7 +1310,7 @@
""",
"""\
<document source="test data">
- <section dupnames="foo" ids="foo-1">
+ <section dupnames="foo">
<title>
foo
<system_message backrefs="foo" level="1" line="5" source="test data" type="INFO">
Modified: trunk/docutils/test/test_transforms/test_sectnum.py
===================================================================
--- trunk/docutils/test/test_transforms/test_sectnum.py 2026-07-14 13:31:13 UTC (rev 10380)
+++ trunk/docutils/test/test_transforms/test_sectnum.py 2026-07-14 13:31:29 UTC (rev 10381)
@@ -20,7 +20,7 @@
from docutils.frontend import get_default_settings
from docutils.parsers.rst import Parser
-from docutils.transforms.references import SectionIDs, Substitutions
+from docutils.transforms.references import Substitutions
from docutils.transforms.universal import TestMessages
from docutils.utils import new_document
@@ -46,7 +46,7 @@
totest = {}
-totest['section_numbers'] = ((SectionIDs, Substitutions), [
+totest['section_numbers'] = ((Substitutions,), [
["""\
.. sectnum::
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|