|
From: <mi...@us...> - 2026-07-15 18:57:59
|
Revision: 10383
http://sourceforge.net/p/docutils/code/10383
Author: milde
Date: 2026-07-15 18:57:56 +0000 (Wed, 15 Jul 2026)
Log Message:
-----------
"lazy IDs": postpone generation of IDs for explicit targets.
Generate IDs for explicit targets after parsing is complete:
`nodes.document.note_explicit_target()` only generates an ID for the target,
if the "legacy_ids" setting is True.
The `transforms.references.PropagateTargets` transform adds IDs to
internal explicit targets (which may also be <topics> or other elements)
before "propagating" empty targets.
`transforms.references.Footnotes.number_footnote_references()`
sets IDs on footnotes with "reference name" but no ID.
This is a precondition for a future check whether the destination of
to-be-propagated targets is an external or indirect target that does
not require an ID. For example in
~~~
.. _e.g.:
.. _example: eg.html
~~~
the second target may become `<target names="example e.g." refuri="eg.html">`
instead of `<target ids="e-g" names="example e.g." refuri="eg.html">`.
Adapt tests: the output of parser tests has no IDs for explicit targets,
nor has the output of transform tests that do not run the `PropagateTargets`
transform.
Modified Paths:
--------------
trunk/docutils/docutils/nodes.py
trunk/docutils/docutils/transforms/references.py
trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py
trunk/docutils/test/test_parsers/test_rst/test_inline_markup.py
trunk/docutils/test/test_parsers/test_rst/test_targets.py
trunk/docutils/test/test_transforms/test_doctitle.py
trunk/docutils/test/test_transforms/test_hyperlinks.py
trunk/docutils/test/test_transforms/test_transitions.py
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/docutils/nodes.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -2177,8 +2177,7 @@
def note_explicit_target(self, target: Element,
msgnode: Element|None = None) -> None:
self.note_names(target, msgnode, explicit=True)
- if (getattr(self.settings, "legacy_ids", True)
- or 'refuri' not in target and 'refname' not in target):
+ if getattr(self.settings, "legacy_ids", True):
self.set_id(target, msgnode)
def note_refname(self, node: Element) -> None:
Modified: trunk/docutils/docutils/transforms/references.py
===================================================================
--- trunk/docutils/docutils/transforms/references.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/docutils/transforms/references.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -42,14 +42,15 @@
Given the following nodes::
- <target ids="internal1" names="internal1">
+ <target names="internal1">
<target anonymous="1" ids="id1">
- <target ids="internal2" names="internal2">
+ <target names="internal2">
<paragraph>
This is a test.
- `PropagateTargets` propagates the ids and names of the internal
- targets preceding the paragraph to the paragraph itself::
+ `PropagateTargets` ensures internal targets have an ID and propagates
+ the IDs and names of the internal targets preceding the paragraph
+ to the paragraph itself::
<target refid="internal1">
<target anonymous="1" refid="id1">
@@ -61,6 +62,17 @@
default_priority = 260
def apply(self) -> None:
+ # Ensure explicit internal targets ("named" elements) have an ID:
+ if not getattr(self.document.settings, "legacy_ids", True):
+ for name, node in self.document.names.items():
+ # Skip targets with duplicate or implicit names:
+ if node is None or not self.document.nametypes[name]:
+ continue
+ # Skip external or indirect targets:
+ if 'refid' in node or 'refname' in node or 'refuri' in node:
+ continue
+ self.document.set_id(node)
+ # Now propatate internal <target>s:
for target in self.document.findall(nodes.target):
# Only block-level targets without reference (like ".. _target:"):
if (len(target) or isinstance(target.parent, nodes.TextElement)
@@ -590,8 +602,9 @@
ref.replace_self(prb)
break
ref += nodes.Text(label)
- id = self.document.nameids[label]
- footnote = self.document.ids[id]
+ footnote = self.document.names[label]
+ id = (self.document.nameids.get(label)
+ or self.document.set_id(footnote))
ref['refid'] = id
self.document.note_refid(ref)
assert len(ref['ids']) == 1
Modified: trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/test/test_parsers/test_rst/test_directives/test_include.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -179,7 +179,7 @@
<section names="include\\ test">
<title>
Include Test
- <literal_block classes="test" ids="my-name" names="my\\ name" source="{include1}" xml:space="preserve">
+ <literal_block classes="test" names="my\\ name" source="{include1}" xml:space="preserve">
Inclusion 1
-----------
\n\
@@ -244,7 +244,7 @@
<document source="test data">
<paragraph>
Include code
- <literal_block classes="code test" ids="my-name" names="my\\ name" source="{include1}" xml:space="preserve">
+ <literal_block classes="code test" names="my\\ name" source="{include1}" xml:space="preserve">
Inclusion 1
-----------
\n\
Modified: trunk/docutils/test/test_parsers/test_rst/test_inline_markup.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_inline_markup.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/test/test_parsers/test_rst/test_inline_markup.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -1168,10 +1168,10 @@
Report duplicate refname.
<paragraph>
Explicit targets: \n\
- <target ids="file-txt" names="file.txt">
+ <target names="file.txt">
file.txt
, \n\
- <target ids="file-html" names="file.html">
+ <target names="file.html">
file.html
.
<system_message level="1" line="6" source="test data" type="INFO">
@@ -1295,10 +1295,10 @@
Duplicate refnames in references with embedded alias.
<paragraph>
Explicit targets: \n\
- <target ids="tg1" names="tg1">
+ <target names="tg1">
tg1
and \n\
- <target ids="tg2" names="tg2">
+ <target names="tg2">
tg2
.
<system_message level="1" line="6" source="test data" type="INFO">
@@ -1334,19 +1334,19 @@
"""\
<document source="test data">
<paragraph>
- <target ids="target" names="target">
+ <target names="target">
target
<paragraph>
Here is \n\
- <target ids="another-target" names="another\\ target">
+ <target names="another\\ target">
another target
in some text. And \n\
- <target ids="yet-another-target" names="yet\\ another\\ target">
+ <target names="yet\\ another\\ target">
yet
another target
, spanning lines.
<paragraph>
- <target ids="here-is-a-target" names="here\\ is\\ a\\ target">
+ <target names="here\\ is\\ a\\ target">
Here is a TaRgeT
with case and spacial difficulties.
"""],
@@ -1357,10 +1357,10 @@
<document source="test data">
<paragraph>
l'
- <target ids="target1" names="target1">
+ <target names="target1">
target1
and l\u2019
- <target ids="target2" names="target2">
+ <target names="target2">
target2
with apostrophe
"""],
@@ -1373,21 +1373,21 @@
<document source="test data">
<paragraph>
quoted '
- <target ids="target1" names="target1">
+ <target names="target1">
target1
', quoted "
- <target ids="target2" names="target2">
+ <target names="target2">
target2
",
quoted \u2018
- <target ids="target3" names="target3">
+ <target names="target3">
target3
\u2019, quoted \u201c
- <target ids="target4" names="target4">
+ <target names="target4">
target4
\u201d,
quoted \xab
- <target ids="target5" names="target5">
+ <target names="target5">
target5
\xbb
"""],
@@ -1399,19 +1399,19 @@
"""\
<document source="test data">
<paragraph>
- <target ids="target1" names="'target1'">
+ <target names="'target1'">
'target1'
with quotes, \n\
- <target ids="target2" names=""target2"">
+ <target names=""target2"">
"target2"
with quotes,
- <target ids="target3" names="\u2018target3\u2019">
+ <target names="\u2018target3\u2019">
\u2018target3\u2019
with quotes, \n\
- <target ids="target4" names="\u201ctarget4\u201d">
+ <target names="\u201ctarget4\u201d">
\u201ctarget4\u201d
with quotes,
- <target ids="target5" names="\xabtarget5\xbb">
+ <target names="\xabtarget5\xbb">
\xabtarget5\xbb
with quotes
"""],
Modified: trunk/docutils/test/test_parsers/test_rst/test_targets.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_targets.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/test/test_parsers/test_rst/test_targets.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -53,7 +53,7 @@
""",
"""\
<document source="test data">
- <target ids="target" names="target">
+ <target names="target">
<paragraph>
(Internal hyperlink target.)
"""],
@@ -62,7 +62,7 @@
""",
"""\
<document source="test data">
- <target ids="optional-space-before-colon" names="optional\\ space\\ before\\ colon">
+ <target names="optional\\ space\\ before\\ colon">
"""],
[r"""
External hyperlink targets:
@@ -115,9 +115,9 @@
""",
"""\
<document source="test data">
- <target ids="a-long-target-name" names="a\\ long\\ target\\ name">
- <target ids="a-target-name-including-a-colon-quoted" names="a\\ target\\ name:\\ including\\ a\\ colon\\ (quoted)">
- <target ids="a-target-name-including-a-colon-escaped" names="a\\ target\\ name:\\ including\\ a\\ colon\\ (escaped)">
+ <target names="a\\ long\\ target\\ name">
+ <target names="a\\ target\\ name:\\ including\\ a\\ colon\\ (quoted)">
+ <target names="a\\ target\\ name:\\ including\\ a\\ colon\\ (escaped)">
"""],
["""\
.. _`target: No matching backquote.
@@ -144,8 +144,8 @@
""",
"""\
<document source="test data">
- <target ids="a-very-long-target-name-split-across-lines" names="a\\ very\\ long\\ target\\ name,\\ split\\ across\\ lines">
- <target ids="and-another-with-backquotes" names="and\\ another,\\ with\\ backquotes">
+ <target names="a\\ very\\ long\\ target\\ name,\\ split\\ across\\ lines">
+ <target names="and\\ another,\\ with\\ backquotes">
"""],
["""\
External hyperlink:
@@ -265,7 +265,7 @@
<document source="test data">
<paragraph>
Duplicate indirect \n\
- <target ids="targets" names="targets">
+ <target names="targets">
targets
(same refname):
<target names="link" refname="targets">
@@ -330,7 +330,7 @@
<system_message level="1" line="6" source="test data" type="INFO">
<paragraph>
Target name overrides implicit target name "title".
- <target ids="title" names="title">
+ <target names="title">
<paragraph>
Paragraph.
"""],
@@ -376,19 +376,19 @@
<document source="test data">
<paragraph>
Duplicate explicit targets.
- <target dupnames="title" ids="title">
+ <target dupnames="title">
<paragraph>
First.
<system_message level="2" line="7" source="test data" type="WARNING">
<paragraph>
Duplicate explicit target name: "title".
- <target dupnames="title" ids="title-1">
+ <target dupnames="title">
<paragraph>
Second.
<system_message level="2" line="11" source="test data" type="WARNING">
<paragraph>
Duplicate explicit target name: "title".
- <target dupnames="title" ids="title-2">
+ <target dupnames="title">
<paragraph>
Third.
"""],
@@ -409,7 +409,7 @@
<document source="test data">
<paragraph>
Duplicate explicit/directive targets.
- <target dupnames="title" ids="title">
+ <target dupnames="title">
<paragraph>
First.
<rubric dupnames="title" ids="title-1">
@@ -471,7 +471,7 @@
<system_message level="2" line="12" source="test data" type="WARNING">
<paragraph>
Duplicate explicit target name: "target".
- <target dupnames="target" ids="target-2">
+ <target dupnames="target">
<paragraph>
Explicit internal target.
<system_message level="2" line="16" source="test data" type="WARNING">
@@ -482,10 +482,10 @@
<line>
Do not insert <system_message> element for duplicate
<line>
- <target dupnames="target" ids="target-3">
+ <target dupnames="target" ids="target-2">
target
, if this results in an invalid doctree.
- <rubric dupnames="target" ids="target-4">
+ <rubric dupnames="target" ids="target-3">
directive with target
<field_list>
<field>
@@ -496,7 +496,7 @@
with
<field>
<field_name>
- <target dupnames="target" ids="target-5">
+ <target dupnames="target" ids="target-4">
target
<field_body>
<paragraph>
Modified: trunk/docutils/test/test_transforms/test_doctitle.py
===================================================================
--- trunk/docutils/test/test_transforms/test_doctitle.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/test/test_transforms/test_doctitle.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -227,7 +227,7 @@
Title
<substitution_definition names="foo">
bar
- <target ids="invisible-target" names="invisible\\ target">
+ <target names="invisible\\ target">
<paragraph>
This title should be the document title despite the
substitution_definition.
Modified: trunk/docutils/test/test_transforms/test_hyperlinks.py
===================================================================
--- trunk/docutils/test/test_transforms/test_hyperlinks.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/test/test_transforms/test_hyperlinks.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -1485,7 +1485,105 @@
<reference refid="internal">
<image uri="picture.png">
"""],
+# TODO: Anonymous links to a "clickable image should go
+# to the image, not the image's click-target!
["""\
+.. _img1:
+.. image:: pic1.png
+ :target: uri1.html
+__
+.. image:: pic2.png
+__
+.. image:: pic3.png
+ :target: uri3.html
+
+Named link to img1_ with target and anonymous links to
+the targetless img2__ and
+img3__ with target (sic!).
+""",
+"""\
+<document source="test data">
+ <target refid="img1">
+ <reference ids="img1" names="img1" refuri="uri1.html">
+ <image uri="pic1.png">
+ <target anonymous="1" refid="target-1">
+ <image ids="target-1" uri="pic2.png">
+ <target anonymous="1" refid="target-2">
+ <reference ids="target-2" refuri="uri3.html">
+ <image uri="pic3.png">
+ <paragraph>
+ Named link to \n\
+ <reference refid="img1">
+ img1
+ with target and anonymous links to
+ the targetless \n\
+ <reference anonymous="1" refid="target-1">
+ img2
+ and
+ <reference anonymous="1" refuri="uri3.html">
+ img3
+ with target (sic!).
+"""],
+["""\
+__
+__
+.. image:: pic1.png
+ :target: uri1.html
+
+Two anonymous__ links to an `image with target`__ (sic!).
+
+.. _named:
+__
+.. image:: pic2.png
+ :target: uri2.html
+
+Named_ and anonymous__ link to an image with target (sic!).
+
+__
+.. _named link:
+.. image:: pic3.png
+ :target: uri3.html
+
+Anonymous__ and `named link`_ to an image with target (sic!).
+""",
+"""\
+<document source="test data">
+ <target anonymous="1" refid="target-1">
+ <target anonymous="1" refid="target-2">
+ <reference ids="target-2 target-1" refuri="uri1.html">
+ <image uri="pic1.png">
+ <paragraph>
+ Two \n\
+ <reference anonymous="1" refuri="uri1.html">
+ anonymous
+ links to an \n\
+ <reference anonymous="1" refuri="uri1.html">
+ image with target
+ (sic!).
+ <target refid="named">
+ <target anonymous="1" refid="target-3">
+ <reference ids="target-3 named" names="named" refuri="uri2.html">
+ <image uri="pic2.png">
+ <paragraph>
+ <reference refid="named">
+ Named
+ and \n\
+ <reference anonymous="1" refuri="uri2.html">
+ anonymous
+ link to an image with target (sic!).
+ <target anonymous="1" refid="target-4">
+ <target refid="named-link">
+ <reference ids="named-link target-4" names="named\\ link" refuri="uri3.html">
+ <image uri="pic3.png">
+ <paragraph>
+ <reference anonymous="1" refuri="uri3.html">
+ Anonymous
+ and \n\
+ <reference refid="named-link">
+ named link
+ to an image with target (sic!).
+"""],
+["""\
.. __: http://full
__
__ http://simplified
Modified: trunk/docutils/test/test_transforms/test_transitions.py
===================================================================
--- trunk/docutils/test/test_transforms/test_transitions.py 2026-07-14 13:32:05 UTC (rev 10382)
+++ trunk/docutils/test/test_transforms/test_transitions.py 2026-07-15 18:57:56 UTC (rev 10383)
@@ -198,7 +198,7 @@
<system_message level="2" line="3" source="test data" type="WARNING">
<paragraph>
Transition at the end of the document.
- <target ids="anchor" names="anchor">
+ <target names="anchor">
<substitution_definition names="substitution\\ reference">
is invisible
"""],
@@ -316,7 +316,7 @@
<footer>
<paragraph>
will move away
- <target ids="anchor" names="anchor">
+ <target names="anchor">
<substitution_definition names="substitution\\ reference">
is invisible
<transition classes="classy">
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|