mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-10-13 17:02:12 -05:00
Refactor latex_show_urls processor to Transform class
This commit is contained in:
1 parent
885b997a25
commit
9fec96d327
3 files changed
+100
-19
No files matched your search
+90
-16
@@ -18,6 +18,7 @@ from os import path
|
||||
|
||||
from six import itervalues, text_type
|
||||
from docutils import nodes, writers
|
||||
from docutils.transforms import Transform
|
||||
from docutils.writers.latex2e import Babel
|
||||
|
||||
from sphinx import addnodes
|
||||
@@ -69,6 +70,8 @@ FOOTER = r'''
|
||||
\end{document}
|
||||
'''
|
||||
|
||||
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
|
||||
|
||||
|
||||
class collected_footnote(nodes.footnote):
|
||||
"""Footnotes that are collected are assigned this class."""
|
||||
@@ -98,6 +101,8 @@ class LaTeXWriter(writers.Writer):
|
||||
self.builder.translator_class or LaTeXTranslator)
|
||||
|
||||
def translate(self):
|
||||
transform = ShowUrlsTransform(self.document)
|
||||
transform.apply()
|
||||
visitor = self.translator_class(self.document, self.builder)
|
||||
self.document.walkabout(visitor)
|
||||
self.output = visitor.astext()
|
||||
@@ -126,6 +131,89 @@ if hasattr(Babel, '_ISO639_TO_BABEL'):
|
||||
Babel._ISO639_TO_BABEL['sl'] = 'slovene'
|
||||
|
||||
|
||||
class ShowUrlsTransform(Transform):
|
||||
expanded = False
|
||||
|
||||
def apply(self):
|
||||
self.expand_show_urls()
|
||||
if self.expanded:
|
||||
self.renumber_footnotes()
|
||||
|
||||
def expand_show_urls(self):
|
||||
show_urls = self.document.settings.env.config.latex_show_urls
|
||||
if show_urls is False or show_urls == 'no':
|
||||
return
|
||||
|
||||
for node in self.document.traverse(nodes.reference):
|
||||
uri = node.get('refuri', '')
|
||||
if uri.startswith(URI_SCHEMES):
|
||||
if uri.startswith('mailto:'):
|
||||
uri = uri[7:]
|
||||
if node.astext() != uri:
|
||||
index = node.parent.index(node)
|
||||
if show_urls == 'footnote':
|
||||
footnote_nodes = self.create_footnote(uri)
|
||||
for i, fn in enumerate(footnote_nodes):
|
||||
node.parent.insert(index + i + 1, fn)
|
||||
|
||||
self.expanded = True
|
||||
else: # all other true values (b/w compat)
|
||||
textnode = nodes.Text(" (%s)" % uri)
|
||||
node.parent.insert(index + 1, textnode)
|
||||
|
||||
def create_footnote(self, uri):
|
||||
label = nodes.label('', '#')
|
||||
para = nodes.paragraph()
|
||||
para.append(nodes.Text(uri))
|
||||
footnote = nodes.footnote(uri, label, para, auto=1)
|
||||
footnote['names'].append('#')
|
||||
self.document.note_autofootnote(footnote)
|
||||
|
||||
label = nodes.Text('#')
|
||||
footnote_ref = nodes.footnote_reference('[#]_', label, auto=1,
|
||||
refid=footnote['ids'][0])
|
||||
self.document.note_autofootnote_ref(footnote_ref)
|
||||
footnote.add_backref(footnote_ref['ids'][0])
|
||||
|
||||
return [footnote, footnote_ref]
|
||||
|
||||
def renumber_footnotes(self):
|
||||
def is_used_number(number):
|
||||
for node in self.document.traverse(nodes.footnote):
|
||||
if not node.get('auto') and number in node['names']:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def is_auto_footnote(node):
|
||||
return isinstance(node, nodes.footnote) and node.get('auto')
|
||||
|
||||
def footnote_ref_by(ids):
|
||||
def is_footnote_ref(node):
|
||||
return isinstance(node, nodes.footnote_reference) and ids[0] == node['refid']
|
||||
|
||||
return is_footnote_ref
|
||||
|
||||
startnum = 1
|
||||
for footnote in self.document.traverse(is_auto_footnote):
|
||||
while True:
|
||||
label = str(startnum)
|
||||
startnum += 1
|
||||
if not is_used_number(label):
|
||||
break
|
||||
|
||||
old_label = footnote[0].astext()
|
||||
footnote.remove(footnote[0])
|
||||
footnote.insert(0, nodes.label('', label))
|
||||
if old_label in footnote['names']:
|
||||
footnote['names'].remove(old_label)
|
||||
footnote['names'].append(label)
|
||||
|
||||
for footnote_ref in self.document.traverse(footnote_ref_by(footnote['ids'])):
|
||||
footnote_ref.remove(footnote_ref[0])
|
||||
footnote_ref += nodes.Text(label)
|
||||
|
||||
|
||||
class Table(object):
|
||||
def __init__(self):
|
||||
self.col = 0
|
||||
@@ -1399,23 +1487,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
||||
uri = '%' + self.curfilestack[-1] + '#' + node['refid']
|
||||
if self.in_title or not uri:
|
||||
self.context.append('')
|
||||
elif uri.startswith('mailto:') or uri.startswith('http:') or \
|
||||
uri.startswith('https:') or uri.startswith('ftp:'):
|
||||
elif uri.startswith(URI_SCHEMES):
|
||||
self.body.append('\\href{%s}{' % self.encode_uri(uri))
|
||||
# if configured, put the URL after the link
|
||||
show_urls = self.builder.config.latex_show_urls
|
||||
if uri.startswith('mailto:'):
|
||||
uri = uri[7:]
|
||||
if node.astext() != uri and show_urls and show_urls != 'no':
|
||||
if show_urls == 'footnote' and not \
|
||||
(self.in_footnote or self.in_caption):
|
||||
# obviously, footnotes in footnotes are not going to work
|
||||
self.context.append(
|
||||
r'}\footnote{%s}' % self.encode_uri(uri))
|
||||
else: # all other true values (b/w compat)
|
||||
self.context.append('} (%s)' % self.encode_uri(uri))
|
||||
else:
|
||||
self.context.append('}')
|
||||
self.context.append('}')
|
||||
elif uri.startswith('#'):
|
||||
# references to labels in the same document
|
||||
id = self.curfilestack[-1] + ':' + uri[1:]
|
||||
|
||||
@@ -19,12 +19,14 @@ The section with a reference to [AuthorYear]_
|
||||
|
||||
.. rubric:: The rubric title with a reference to [AuthorYear]_
|
||||
|
||||
.. [#] First
|
||||
|
||||
* First footnote: [#]_
|
||||
* Second footnote: [1]_
|
||||
* `Sphinx <http://sphinx-doc.org/>`_
|
||||
* Third footnote: [#]_
|
||||
* `URL including tilde <http://sphinx-doc.org/~test/>`_
|
||||
|
||||
.. [AuthorYear] Author, Title, Year
|
||||
.. [#] First
|
||||
.. [1] Second
|
||||
.. [#] Third
|
||||
@@ -349,6 +349,8 @@ def test_latex_show_urls_is_inline(app, status, warning):
|
||||
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
|
||||
assert '\\href{http://sphinx-doc.org/}{Sphinx} (http://sphinx-doc.org/)' in result
|
||||
assert 'Third footnote: \\footnote[3]{\nThird\n}' in result
|
||||
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde} '
|
||||
'(http://sphinx-doc.org/\\textasciitilde{}test/)' in result)
|
||||
|
||||
|
||||
@with_app(buildername='latex', testroot='footnotes',
|
||||
@@ -362,8 +364,10 @@ def test_latex_show_urls_is_footnote(app, status, warning):
|
||||
assert 'First footnote: \\footnote[2]{\nFirst\n}' in result
|
||||
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
|
||||
assert ('\\href{http://sphinx-doc.org/}{Sphinx}'
|
||||
'\\footnote{http://sphinx-doc.org/}' in result)
|
||||
assert 'Third footnote: \\footnote[3]{\nThird\n}' in result
|
||||
'\\footnote[3]{\nhttp://sphinx-doc.org/\n}' in result)
|
||||
assert 'Third footnote: \\footnote[5]{\nThird\n}' in result
|
||||
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
|
||||
'\\footnote[4]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
|
||||
|
||||
|
||||
@with_app(buildername='latex', testroot='footnotes',
|
||||
@@ -378,3 +382,4 @@ def test_latex_show_urls_is_no(app, status, warning):
|
||||
assert 'Second footnote: \\footnote[1]{\nSecond\n}' in result
|
||||
assert '\\href{http://sphinx-doc.org/}{Sphinx}' in result
|
||||
assert 'Third footnote: \\footnote[3]{\nThird\n}' in result
|
||||
assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result
|
||||
Reference in new issue
Block a user