From 5efecd2150d615aaa6b788d6591dff5791150c3c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 8 Feb 2018 21:46:59 +0900 Subject: [PATCH] Add :confval:`html_css_files` --- CHANGES | 1 + doc/config.rst | 19 +++++++++++--- sphinx/builders/html.py | 26 ++++++++++++++++--- tests/roots/test-html_assets/conf.py | 2 ++ .../test-html_assets/static/js/custom.js | 0 tests/test_build_html.py | 13 +++++++--- 6 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 tests/roots/test-html_assets/static/js/custom.js diff --git a/CHANGES b/CHANGES index 0788e1c77..11cdf4ea7 100644 --- a/CHANGES +++ b/CHANGES @@ -59,6 +59,7 @@ Features added * LaTeX: new key ``'fvset'`` for :confval:`latex_elements`. For XeLaTeX/LuaLaTeX its default sets ``fanvyvrb`` to use normal, not small, fontsize in code-blocks (refs: #4793) +* Add :confval:`html_css_files` for adding CSS files from configuration Bugs fixed ---------- diff --git a/doc/config.rst b/doc/config.rst index 04f3c2d7c..97e43e645 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -59,9 +59,6 @@ Important points to note: Note that the current builder tag is not available in ``conf.py``, as it is created *after* the builder is initialized. -.. seealso:: Additional configurations, such as adding stylesheets, - javascripts, builders, etc. can be made through the :doc:`/extdev/appapi`. - General configuration --------------------- @@ -846,6 +843,22 @@ that use Sphinx's HTMLWriter class. The image file will be copied to the ``_static`` directory of the output HTML, but only if the file does not already exist there. +.. confval:: html_css_files + + A list of CSS files. The entry must be a *filename* string or a tuple + containing the *filename* string and the *attributes* dictionary. The + *filename* must be relative to the :confval:`html_static_path`, or a full URI + with scheme like ``http://example.org/style.css``. The *attributes* is used + for attributes of ```` tag. It defaults to an empty list. + + Example:: + + html_css_files = ['custom.css' + 'https://example.com/css/custom.css', + ('print.css', {'media': 'print'})] + + .. versionadded:: 1.8 + .. confval:: html_static_path A list of paths that contain custom static files (such as style diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index c42669675..25538ac17 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -154,6 +154,7 @@ class Stylesheet(text_type): self.filename = filename self.attributes = attributes self.attributes.setdefault('rel', 'stylesheet') + self.attributes.setdefault('type', 'text/css') if args: # old style arguments (rel, title) self.attributes['rel'] = args[0] self.attributes['title'] = args[1] @@ -342,6 +343,22 @@ class StandaloneHTMLBuilder(Builder): for filename, attrs in self.app.registry.css_files: self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore + for entry in self.get_builder_config('css_files', 'html'): + if isinstance(entry, string_types): + filename = entry + attrs = {} + else: + try: + filename, attrs = entry + except (TypeError, ValueError): + logger.warning('invalid css_file: %r', entry) + continue + + if '://' not in filename: + filename = path.join('_static', filename) + + self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore + @property def default_translator_class(self): # type: () -> nodes.NodeVisitor @@ -1008,9 +1025,11 @@ class StandaloneHTMLBuilder(Builder): def css_tag(css): # type: (Stylesheet) -> unicode - attrs = ['%s="%s"' % (key, htmlescape(value, True)) - for key, value in css.attributes.items() - if value is not None] + attrs = [] + for key in sorted(css.attributes): + value = css.attributes[key] + if value is not None: + attrs.append('%s="%s"' % (key, htmlescape(value, True))) attrs.append('href="%s"' % pathto(css.filename, resource=True)) return '' % ' '.join(attrs) ctx['css_tag'] = css_tag @@ -1468,6 +1487,7 @@ def setup(app): app.add_config_value('html_style', None, 'html', string_classes) app.add_config_value('html_logo', None, 'html', string_classes) app.add_config_value('html_favicon', None, 'html', string_classes) + app.add_config_value('html_css_files', [], 'html') app.add_config_value('html_static_path', [], 'html') app.add_config_value('html_extra_path', [], 'html') app.add_config_value('html_last_updated_fmt', None, 'html', string_classes) diff --git a/tests/roots/test-html_assets/conf.py b/tests/roots/test-html_assets/conf.py index a17e417a3..c61f0b42c 100644 --- a/tests/roots/test-html_assets/conf.py +++ b/tests/roots/test-html_assets/conf.py @@ -6,4 +6,6 @@ version = '1.4.4' html_static_path = ['static', 'subdir'] html_extra_path = ['extra', 'subdir'] +html_css_files = ['css/style.css', + ('https://example.com/custom.css', {'title': 'title', 'media': 'print'})] exclude_patterns = ['**/_build', '**/.htpasswd'] diff --git a/tests/roots/test-html_assets/static/js/custom.js b/tests/roots/test-html_assets/static/js/custom.js new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 1ee5eb473..655feec03 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1094,9 +1094,10 @@ def test_html_assets(app): assert not (app.outdir / '_static' / '.htpasswd').exists() assert (app.outdir / '_static' / 'API.html').exists() assert (app.outdir / '_static' / 'API.html').text() == 'Sphinx-1.4.4' - assert (app.outdir / '_static' / 'css/style.css').exists() + assert (app.outdir / '_static' / 'css' / 'style.css').exists() + assert (app.outdir / '_static' / 'js' / 'custom.js').exists() assert (app.outdir / '_static' / 'rimg.png').exists() - assert not (app.outdir / '_static' / '_build/index.html').exists() + assert not (app.outdir / '_static' / '_build' / 'index.html').exists() assert (app.outdir / '_static' / 'background.png').exists() assert not (app.outdir / '_static' / 'subdir' / '.htaccess').exists() assert not (app.outdir / '_static' / 'subdir' / '.htpasswd').exists() @@ -1107,11 +1108,17 @@ def test_html_assets(app): assert (app.outdir / 'API.html_t').exists() assert (app.outdir / 'css/style.css').exists() assert (app.outdir / 'rimg.png').exists() - assert not (app.outdir / '_build/index.html').exists() + assert not (app.outdir / '_build' / 'index.html').exists() assert (app.outdir / 'background.png').exists() assert (app.outdir / 'subdir' / '.htaccess').exists() assert not (app.outdir / 'subdir' / '.htpasswd').exists() + # html_css_files + content = (app.outdir / 'index.html').text() + assert '' in content + assert ('' in content) + @pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_copy_source': False}) def test_html_copy_source(app):