diff --git a/CHANGES b/CHANGES index 027900621..93c7d9f34 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Bugs fixed * #5325: latex: cross references has been broken by multiply labeled objects * C++, fixes for symbol addition and lookup. Lookup should no longer break in partial builds. See also #5337. +* #5348: download reference to remote file is not displayed Testing -------- diff --git a/sphinx/environment/collectors/asset.py b/sphinx/environment/collectors/asset.py index 70faf108c..725431dfa 100644 --- a/sphinx/environment/collectors/asset.py +++ b/sphinx/environment/collectors/asset.py @@ -128,13 +128,16 @@ class DownloadFileCollector(EnvironmentCollector): """Process downloadable file paths. """ for node in doctree.traverse(addnodes.download_reference): targetname = node['reftarget'] - rel_filename, filename = app.env.relfn2path(targetname, app.env.docname) - app.env.dependencies[app.env.docname].add(rel_filename) - if not os.access(filename, os.R_OK): - logger.warning(__('download file not readable: %s') % filename, - location=node, type='download', subtype='not_readable') - continue - node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename) + if '://' in targetname: + node['refuri'] = targetname + else: + rel_filename, filename = app.env.relfn2path(targetname, app.env.docname) + app.env.dependencies[app.env.docname].add(rel_filename) + if not os.access(filename, os.R_OK): + logger.warning(__('download file not readable: %s') % filename, + location=node, type='download', subtype='not_readable') + continue + node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename) def setup(app): diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 797b5828e..e2899e8a4 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -564,10 +564,20 @@ class HTMLTranslator(BaseTranslator): def visit_download_reference(self, node): # type: (nodes.Node) -> None - if self.builder.download_support and node.hasattr('filename'): - self.body.append( - '' % - posixpath.join(self.builder.dlpath, node['filename'])) + atts = {'class': 'reference download', + 'download': ''} + + if not self.builder.download_support: + self.context.append('') + elif 'refuri' in node: + atts['class'] += ' external' + atts['href'] = node['refuri'] + self.body.append(self.starttag(node, 'a', '', **atts)) + self.context.append('') + elif 'filename' in node: + atts['class'] += ' internal' + atts['href'] = posixpath.join(self.builder.dlpath, node['filename']) + self.body.append(self.starttag(node, 'a', '', **atts)) self.context.append('') else: self.context.append('') diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 74dc827a1..c14775b9c 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -510,10 +510,20 @@ class HTML5Translator(BaseTranslator): def visit_download_reference(self, node): # type: (nodes.Node) -> None - if self.builder.download_support and node.hasattr('filename'): - self.body.append( - '' % - posixpath.join(self.builder.dlpath, node['filename'])) + atts = {'class': 'reference download', + 'download': ''} + + if not self.builder.download_support: + self.context.append('') + elif 'refuri' in node: + atts['class'] += ' external' + atts['href'] = node['refuri'] + self.body.append(self.starttag(node, 'a', '', **atts)) + self.context.append('') + elif 'filename' in node: + atts['class'] += ' internal' + atts['href'] = posixpath.join(self.builder.dlpath, node['filename']) + self.body.append(self.starttag(node, 'a', '', **atts)) self.context.append('') else: self.context.append('') diff --git a/tests/roots/test-roles-download/conf.py b/tests/roots/test-roles-download/conf.py new file mode 100644 index 000000000..31e7a6ed4 --- /dev/null +++ b/tests/roots/test-roles-download/conf.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' + +latex_documents = [ + (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report') +] diff --git a/tests/roots/test-roles-download/dummy.dat b/tests/roots/test-roles-download/dummy.dat new file mode 100644 index 000000000..e69de29bb diff --git a/tests/roots/test-roles-download/index.rst b/tests/roots/test-roles-download/index.rst new file mode 100644 index 000000000..41cda621a --- /dev/null +++ b/tests/roots/test-roles-download/index.rst @@ -0,0 +1,6 @@ +test-roles-download +=================== + +* :download:`dummy.dat` +* :download:`not_found.dat` +* :download:`Sphinx logo ` diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py index f8c1457fa..074e40fb6 100644 --- a/tests/test_build_epub.py +++ b/tests/test_build_epub.py @@ -354,6 +354,22 @@ def test_epub_css_files(app): 'href="https://example.com/custom.css" />' not in content) +@pytest.mark.sphinx('epub', testroot='roles-download') +def test_html_download_role(app, status, warning): + app.build() + assert not (app.outdir / '_downloads' / 'dummy.dat').exists() + + content = (app.outdir / 'index.xhtml').text() + assert ('
  • ' + 'dummy.dat

  • ' in content) + assert ('
  • ' + 'not_found.dat

  • ' in content) + assert ('
  • ' + 'Sphinx logo' + ' [http://www.sphinx-doc.org/en/master' + '/_static/sphinxheader.png]

  • ' in content) + + @pytest.mark.sphinx('epub') def test_run_epubcheck(app): app.build() diff --git a/tests/test_build_html.py b/tests/test_build_html.py index b8286edb3..93f1130bb 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1387,3 +1387,22 @@ def test_html_math_renderer_is_mismatched(make_app, app_params): assert False except ConfigError as exc: assert str(exc) == "Unknown math_renderer 'imgmath' is given." + + +@pytest.mark.sphinx('html', testroot='roles-download') +def test_html_download_role(app, status, warning): + app.build() + assert (app.outdir / '_downloads' / 'dummy.dat').exists() + + content = (app.outdir / 'index.html').text() + assert ('
  • ' + '' + 'dummy.dat
  • ' in content) + assert ('
  • ' + 'not_found.dat
  • ' in content) + assert ('
  • ' + '' + 'Sphinx logo' + '
  • ' in content) diff --git a/tests/test_build_html5.py b/tests/test_build_html5.py index 82050cee1..21da21224 100644 --- a/tests/test_build_html5.py +++ b/tests/test_build_html5.py @@ -321,3 +321,23 @@ def test_html5_output(app, cached_etree_parse, fname, expect): app.build() print(app.outdir / fname) check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect) + + +@pytest.mark.sphinx('html', testroot='roles-download', + confoverrides={'html_experimental_html5_writer': True}) +def test_html_download_role(app, status, warning): + app.build() + assert (app.outdir / '_downloads' / 'dummy.dat').exists() + + content = (app.outdir / 'index.html').text() + assert ('
  • ' + '' + 'dummy.dat

  • ' in content) + assert ('
  • ' + 'not_found.dat

  • ' in content) + assert ('
  • ' + '' + 'Sphinx logo' + '

  • ' in content)