diff options
| author | milde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2019-10-11 10:09:53 +0000 |
|---|---|---|
| committer | milde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2019-10-11 10:09:53 +0000 |
| commit | c8cd68795bd920d72157a9fad7b26049d4614ce9 (patch) | |
| tree | 230fa750031d4d0df8034527475c84d38b9bce9e | |
| parent | 20bb678f2719ce3a5cd3029862a0d3a56a1e6a44 (diff) | |
| download | docutils-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
| -rw-r--r-- | docutils/docutils/nodes.py | 39 | ||||
| -rw-r--r-- | docutils/docutils/transforms/parts.py | 3 |
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') |
