summaryrefslogtreecommitdiff
path: root/docutils
diff options
context:
space:
mode:
authormilde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2019-10-11 10:09:53 +0000
committermilde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2019-10-11 10:09:53 +0000
commitc8cd68795bd920d72157a9fad7b26049d4614ce9 (patch)
tree230fa750031d4d0df8034527475c84d38b9bce9e /docutils
parent20bb678f2719ce3a5cd3029862a0d3a56a1e6a44 (diff)
downloaddocutils-c8cd68795bd920d72157a9fad7b26049d4614ce9.tar.gz
More descriptive auto-IDs
Generate unique ids adding a running number to prefixes based on a) the node "name" (if existing but not unique), b) the new optional argument "suggested_prefix" (used for toc entries), c) the tagname of the object (e.g. footnote, citation, footnote-reference, system-message, ...) Advantages: * Meaningfully named links to ToC entries, footnotes, citations, error messages, and sections with duplicate title. * More stable links (a new footnote does not change backlinks to the ToC, say). For backwards compatibility, this only applies if `settings.auto_id_prefix` ends with a percent sign ("%"). This may become the default in the future. git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk@8403 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'docutils')
-rw-r--r--docutils/docutils/nodes.py39
-rw-r--r--docutils/docutils/transforms/parts.py3
2 files changed, 29 insertions, 13 deletions
diff --git a/docutils/docutils/nodes.py b/docutils/docutils/nodes.py
index 264679db9..d0d3b0a0d 100644
--- a/docutils/docutils/nodes.py
+++ b/docutils/docutils/nodes.py
@@ -20,6 +20,7 @@ hierarchy.
.. _DTD: http://docutils.sourceforge.net/docs/ref/docutils.dtd
"""
from __future__ import print_function
+from collections import Counter
__docformat__ = 'reStructuredText'
@@ -36,7 +37,7 @@ if sys.version_info >= (3, 0):
class _traversal_list():
# auxiliary class to report a FutureWarning
-
+
def __init__(self, iterable):
self.nodes = list(iterable)
@@ -46,10 +47,10 @@ class _traversal_list():
"Docutils > 0.16.")
warnings.warn(msg, FutureWarning, stacklevel=2)
return getattr(self.nodes, name)
-
+
def __iter__(self):
return iter(self.nodes)
-
+
def __len__(self):
# used in Python 2.7 when typecasting to `list` or `tuple`
return len(self.nodes)
@@ -1320,8 +1321,8 @@ class document(Root, Structural, Element):
self.symbol_footnote_start = 0
"""Initial symbol footnote symbol index."""
- self.id_start = 1
- """Initial ID number."""
+ self.id_counter = Counter()
+ """Numbers added to otherwise identical IDs."""
self.parse_messages = []
"""System messages generated while parsing."""
@@ -1355,23 +1356,37 @@ class document(Root, Structural, Element):
domroot.appendChild(self._dom_node(domroot))
return domroot
- def set_id(self, node, msgnode=None):
+ def set_id(self, node, msgnode=None, suggested_prefix=''):
for id in node['ids']:
if id in self.ids and self.ids[id] is not node:
msg = self.reporter.severe('Duplicate ID: "%s".' % id)
if msgnode != None:
msgnode += msg
if not node['ids']:
+ id_prefix = self.settings.id_prefix
+ auto_id_prefix = self.settings.auto_id_prefix
+ id = ''
for name in node['names']:
- id = self.settings.id_prefix + make_id(name)
+ id = id_prefix + make_id(name)
+ # TODO: allow names starting with numbers if `id_prefix`
+ # is non-empty: id = make_id(id_prefix + name)
if id and id not in self.ids:
break
else:
- id = ''
- while not id or id in self.ids:
- id = (self.settings.id_prefix +
- self.settings.auto_id_prefix + str(self.id_start))
- self.id_start += 1
+ if id and auto_id_prefix.endswith('%'):
+ # disambiguate name-derived ID
+ # TODO: remove second condition after announcing change
+ prefix = id + '-'
+ else:
+ prefix = id_prefix + auto_id_prefix
+ if prefix.endswith('%'):
+ prefix = '%s%s-' % (prefix[:-1], suggested_prefix
+ or make_id(node.tagname))
+ while True:
+ self.id_counter[prefix] += 1
+ id = '%s%d' % (prefix, self.id_counter[prefix])
+ if id not in self.ids:
+ break
node['ids'].append(id)
self.ids[id] = node
return id
diff --git a/docutils/docutils/transforms/parts.py b/docutils/docutils/transforms/parts.py
index d6a9ecef1..42e7bab30 100644
--- a/docutils/docutils/transforms/parts.py
+++ b/docutils/docutils/transforms/parts.py
@@ -127,7 +127,8 @@ class Contents(Transform):
entrytext = self.copy_and_filter(title)
reference = nodes.reference('', '', refid=section['ids'][0],
*entrytext)
- ref_id = self.document.set_id(reference)
+ ref_id = self.document.set_id(reference,
+ suggested_prefix='toc-entry')
entry = nodes.paragraph('', '', reference)
item = nodes.list_item('', entry)
if ( self.backlinks in ('entry', 'top')