From: <mi...@us...> - 2024-09-13 08:13:06
|
Revision: 9930 http://sourceforge.net/p/docutils/code/9930 Author: milde Date: 2024-09-13 08:13:03 +0000 (Fri, 13 Sep 2024) Log Message: ----------- Use "unknown_reference_resolver" for LaTeX writer option "use-bibtex". The "latex" writer provides the (provisional) setting "use_bibtex" to defer the resolution of citation references to the backend (LaTeX/BibTeX/LaTeX). Use the `unknown_reference_resolvers` hook of the `TransformSpec` to mark citation references as resolved if BibTeX is used. Advantages: * replaces hard-coded special-case in `transforms.references.DanglingReferencesVisitor` introduced in [r9312], * provides a usage example, * tests the hook with the Docutils test suite without additional overhead. Update docstrings and comments. Modified Paths: -------------- trunk/docutils/HISTORY.rst trunk/docutils/docutils/__init__.py trunk/docutils/docutils/transforms/__init__.py trunk/docutils/docutils/transforms/references.py trunk/docutils/docutils/writers/latex2e/__init__.py Modified: trunk/docutils/HISTORY.rst =================================================================== --- trunk/docutils/HISTORY.rst 2024-09-12 12:57:48 UTC (rev 9929) +++ trunk/docutils/HISTORY.rst 2024-09-13 08:13:03 UTC (rev 9930) @@ -158,6 +158,8 @@ (ignored since at least 2012). - Don't wrap references with custom reference-label_ in a ``\hyperref`` command. + - Provide an "unknown_references_resolver" (cf. `docutils/TransformSpec`) + for citation references resolved with BibTeX (cf. `use_bibtex`_ setting). .. _reference-label: docs/user/config.html#reference-label @@ -3856,9 +3858,9 @@ * docutils/transforms/__init__.py: - Added ``Transformer`` class and completed transform reform. - - Added unknown_reference_resolvers list for each transformer. This list holds - the list of functions provided by each component of the transformer that - help resolve references. + - Added unknown_reference_resolvers list for each transformer. + This list holds the list of functions provided by each component + of the transformer that help resolve references. * docutils/transforms/frontmatter.py: Modified: trunk/docutils/docutils/__init__.py =================================================================== --- trunk/docutils/docutils/__init__.py 2024-09-12 12:57:48 UTC (rev 9929) +++ trunk/docutils/docutils/__init__.py 2024-09-13 08:13:03 UTC (rev 9930) @@ -282,8 +282,11 @@ default_transforms: ClassVar[tuple[()]] = () unknown_reference_resolvers: Sequence[_UnknownReferenceResolver] = () - """List of functions to try to resolve unknown references. + """List of hook functions which assist in resolving references. + Override in subclasses to implement component-specific resolving of + unknown references. + Unknown references have a 'refname' attribute which doesn't correspond to any target in the document. Called when the transforms in `docutils.transforms.references` are unable to find a correct target. @@ -291,7 +294,7 @@ The list should contain functions which will try to resolve unknown references, with the following signature:: - def reference_resolver(node): + def reference_resolver(node: nodes.Element) -> bool: '''Returns boolean: true if resolved, false if not.''' If the function is able to resolve the reference, it should also remove @@ -301,13 +304,20 @@ node.resolved = True Each function must have a "priority" attribute which will affect the order - the unknown_reference_resolvers are run:: + the unknown_reference_resolvers are run + cf. ../docs/api/transforms.html#transform-priority-range-categories :: - reference_resolver.priority = 100 + reference_resolver.priority = 500 - This hook is provided for 3rd party extensions. - Example use case: the `MoinMoin - ReStructured Text Parser` - https://github.com/moinwiki/moin + Examples: + `writers.latex2e.Writer` defines a resolver to mark citation references + as resolved by BibTeX if the "use_bibtex" configuration setting is set. + + The `MoinMoin ReStructured Text Parser`__ provides a resolver for + "WikiWiki links" (currently only in the outdated 1.9 version). + + __ https://github.com/moinwiki/moin-1.9/blob/1.9.11/MoinMoin/parser/ + text_rst.py """ Modified: trunk/docutils/docutils/transforms/__init__.py =================================================================== --- trunk/docutils/docutils/transforms/__init__.py 2024-09-12 12:57:48 UTC (rev 9929) +++ trunk/docutils/docutils/transforms/__init__.py 2024-09-13 08:13:03 UTC (rev 9930) @@ -144,7 +144,7 @@ def populate_from_components(self, components) -> None: """ - Store each component's default transforms and reference resolvers + Store each component's default transforms and reference resolvers. Transforms are stored with default priorities for later sorting. "Unknown reference resolvers" are sorted and stored. @@ -161,7 +161,7 @@ resolvers.extend(component.unknown_reference_resolvers) self.sorted = False # sort transform list in self.apply_transforms() - # Sort and add helper functions to help resolve unknown references. + # Sort and add hook functions helping to resolve unknown references. def keyfun(f): return f.priority resolvers.sort(key=keyfun) Modified: trunk/docutils/docutils/transforms/references.py =================================================================== --- trunk/docutils/docutils/transforms/references.py 2024-09-12 12:57:48 UTC (rev 9929) +++ trunk/docutils/docutils/transforms/references.py 2024-09-13 08:13:03 UTC (rev 9930) @@ -888,37 +888,33 @@ return refname = node['refname'] id = self.document.nameids.get(refname) - if id is None: - for resolver_function in self.unknown_reference_resolvers: - if resolver_function(node): - break - else: - if (getattr(self.document.settings, 'use_bibtex', False) - and isinstance(node, nodes.citation_reference)): - # targets added from BibTeX database by LaTeX - node.resolved = True - return - if refname in self.document.nameids: - msg = self.document.reporter.error( - 'Duplicate target name, cannot be used as a unique ' - 'reference: "%s".' % (node['refname']), base_node=node) - else: - msg = self.document.reporter.error( - f'Unknown target name: "{node["refname"]}".', - base_node=node) - msgid = self.document.set_id(msg) - prb = nodes.problematic( - node.rawsource, node.rawsource, refid=msgid) - try: - prbid = node['ids'][0] - except IndexError: - prbid = self.document.set_id(prb) - msg.add_backref(prbid) - node.replace_self(prb) - else: + if id is not None: + # target found, set refid del node['refname'] node['refid'] = id self.document.ids[id].note_referenced_by(id=id) node.resolved = True + return + # Apply component-specific resolving functions (cf. TransformSpec): + for resolver_function in self.unknown_reference_resolvers: + if resolver_function(node): + return + # Report unresolved references: + if refname in self.document.nameids: + msg = self.document.reporter.error( + 'Duplicate target name, cannot be used as a unique ' + 'reference: "%s".' % (node['refname']), base_node=node) + else: + msg = self.document.reporter.error( + f'Unknown target name: "{node["refname"]}".', + base_node=node) + msgid = self.document.set_id(msg) + prb = nodes.problematic(node.rawsource, node.rawsource, refid=msgid) + try: + prbid = node['ids'][0] + except IndexError: + prbid = self.document.set_id(prb) + msg.add_backref(prbid) + node.replace_self(prb) visit_footnote_reference = visit_citation_reference = visit_reference Modified: trunk/docutils/docutils/writers/latex2e/__init__.py =================================================================== --- trunk/docutils/docutils/writers/latex2e/__init__.py 2024-09-12 12:57:48 UTC (rev 9929) +++ trunk/docutils/docutils/writers/latex2e/__init__.py 2024-09-13 08:13:03 UTC (rev 9930) @@ -253,7 +253,23 @@ def __init__(self) -> None: writers.Writer.__init__(self) self.translator_class = LaTeXTranslator + self.unknown_reference_resolvers = [self.bibtex_reference_resolver] + self.bibtex_reference_resolver.priority = 400 + @staticmethod + def bibtex_reference_resolver(node: nodes.Element) -> bool: + """Mark citation references as resolved if BibTeX is used. + + Cf. `TransformSpec.unknown_reference_resolvers`. + """ + if (isinstance(node, nodes.citation_reference) + and node.document.settings.use_bibtex): + del node['refname'] + node.resolved = True + return True + else: + return False + def get_transforms(self): # Override parent method to add latex-specific transforms return super().get_transforms() + [ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |