From a18c04b955eed9159473046d55b46fb2ee7bc417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Fdez=2E=20Galv=C3=A1n?= Date: Wed, 11 Mar 2015 15:48:40 +0100 Subject: [PATCH 01/14] Allow setting 'rel' and 'title' attributes for stylesheets. --- doc/extdev/appapi.rst | 6 +++++- doc/templating.rst | 13 ++++++++++++- sphinx/application.py | 11 +++++++---- sphinx/themes/basic/layout.html | 20 +++++++++++++++++++- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst index c2ee4cc86..da225dfbf 100644 --- a/doc/extdev/appapi.rst +++ b/doc/extdev/appapi.rst @@ -280,7 +280,7 @@ package. .. versionadded:: 0.5 -.. method:: Sphinx.add_stylesheet(filename) +.. method:: Sphinx.add_stylesheet(filename, rel=None, title=None) Add *filename* to the list of CSS files that the default HTML template will include. Like for :meth:`add_javascript`, the filename must be relative to @@ -288,6 +288,10 @@ package. .. versionadded:: 1.0 + .. versionchanged:: 1.4 + Optional ``rel`` and/or ``title`` attributes can be supplied with the *rel* + and *title* arguments. + .. method:: Sphinx.add_latex_package(packagename, options=None) Add *packagename* to the list of packages that LaTeX source code will include. diff --git a/doc/templating.rst b/doc/templating.rst index 19ed14840..b8acd9965 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -202,8 +202,19 @@ Overriding works like this:: .. data:: css_files - Similar to :data:`script_files`, for CSS files. + Similar to :data:`script_files`, for CSS files:: + {% set css_files = css_files + ["_static/mystyle.css"] %} + + .. versionchanged:: 1.4 + Optionally, ``rel`` and/or ``title`` attributes can be provided by supplying + a Python dictionary, in which case the filename is given in the ``filename`` + key:: + + {% set css_files = css_files + [{"filename":"_static/mystyle.css", "rel":"stylesheet", "title":"Default"}] %} + + The default is no title and ``rel='stylesheet'``, but if only ``title`` + is given, the default is ``rel='alternate stylesheet'``. Helper Functions ~~~~~~~~~~~~~~~~ diff --git a/sphinx/application.py b/sphinx/application.py index b87689e71..b18fc7a42 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -681,14 +681,17 @@ class Sphinx(object): StandaloneHTMLBuilder.script_files.append( posixpath.join('_static', filename)) - def add_stylesheet(self, filename): + def add_stylesheet(self, filename, rel=None, title=None): self.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder + item = {} + if rel is not None: item['rel'] = rel + if title is not None: item['title'] = title if '://' in filename: - StandaloneHTMLBuilder.css_files.append(filename) + item['filename'] = filename else: - StandaloneHTMLBuilder.css_files.append( - posixpath.join('_static', filename)) + item['filename'] = posixpath.join('_static', filename) + StandaloneHTMLBuilder.css_files.append(item) def add_latex_package(self, packagename, options=None): self.debug('[app] adding latex package: %r', packagename) diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index 4c0ebd658..93dc34d57 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -103,7 +103,25 @@ {%- for cssfile in css_files %} - + {%- if cssfile.filename is defined %} + {%- set filename = cssfile.filename %} + {%- else %} + {%- set filename = cssfile %} + {%- endif %} + {%- if cssfile.rel is defined %} + {%- set rel = cssfile.rel %} + {%- endif %} + {%- if cssfile.title is defined and cssfile.title is string %} + {%- if cssfile.rel is not defined %} + {%- set rel = "alternate stylesheet" %} + {%- endif %} + + {%- else %} + {%- if cssfile.rel is not defined %} + {%- set rel = "stylesheet" %} + {%- endif %} + + {%- endif %} {%- endfor %} {%- endmacro %} From 2fdd06be449ef35bad1deaba046e0deedda42707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Fdez=2E=20Galv=C3=A1n?= Date: Wed, 11 Mar 2015 15:58:57 +0100 Subject: [PATCH 02/14] Fix two statements in one line --- sphinx/application.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index b18fc7a42..9405d9686 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -685,8 +685,10 @@ class Sphinx(object): self.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder item = {} - if rel is not None: item['rel'] = rel - if title is not None: item['title'] = title + if rel is not None: + item['rel'] = rel + if title is not None: + item['title'] = title if '://' in filename: item['filename'] = filename else: From 204b9cc5217ae4a307b7d56419e482652e2eca94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Fdez=2E=20Galv=C3=A1n?= Date: Thu, 12 Mar 2015 10:51:45 +0100 Subject: [PATCH 03/14] Changed 'rel' to 'alternate' --- doc/extdev/appapi.rst | 6 +++--- doc/templating.rst | 14 ++++++++------ sphinx/application.py | 6 +++--- sphinx/themes/basic/layout.html | 16 ++++++++-------- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst index da225dfbf..2c85d44be 100644 --- a/doc/extdev/appapi.rst +++ b/doc/extdev/appapi.rst @@ -280,7 +280,7 @@ package. .. versionadded:: 0.5 -.. method:: Sphinx.add_stylesheet(filename, rel=None, title=None) +.. method:: Sphinx.add_stylesheet(filename, alternate=None, title=None) Add *filename* to the list of CSS files that the default HTML template will include. Like for :meth:`add_javascript`, the filename must be relative to @@ -289,8 +289,8 @@ package. .. versionadded:: 1.0 .. versionchanged:: 1.4 - Optional ``rel`` and/or ``title`` attributes can be supplied with the *rel* - and *title* arguments. + Optional ``alternate`` and/or ``title`` attributes can be supplied with + the *alternate* (of boolean type) and *title* (a string) arguments. .. method:: Sphinx.add_latex_package(packagename, options=None) diff --git a/doc/templating.rst b/doc/templating.rst index b8acd9965..20423b391 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -207,14 +207,16 @@ Overriding works like this:: {% set css_files = css_files + ["_static/mystyle.css"] %} .. versionchanged:: 1.4 - Optionally, ``rel`` and/or ``title`` attributes can be provided by supplying - a Python dictionary, in which case the filename is given in the ``filename`` - key:: + Optionally, ``alternate`` and/or ``title`` attributes can be provided by + supplying a Python dictionary, in which case the filename is given in the + ``filename`` key:: - {% set css_files = css_files + [{"filename":"_static/mystyle.css", "rel":"stylesheet", "title":"Default"}] %} + {% set css_files = css_files + [{"filename":"_static/mystyle.css", "alternate":False, "title":"Default"}] %} - The default is no title and ``rel='stylesheet'``, but if only ``title`` - is given, the default is ``rel='alternate stylesheet'``. + The default is no title and ``alternate=False``, but if only ``title`` is + given, the default is ``alternate=True``. If ``alternate`` is ``True``, it + will be translated to ``rel="alternate stylesheet"``, otherwise it will be + ``rel="stylesheet"``. Helper Functions ~~~~~~~~~~~~~~~~ diff --git a/sphinx/application.py b/sphinx/application.py index 9405d9686..a9044fc51 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -681,12 +681,12 @@ class Sphinx(object): StandaloneHTMLBuilder.script_files.append( posixpath.join('_static', filename)) - def add_stylesheet(self, filename, rel=None, title=None): + def add_stylesheet(self, filename, alternate=None, title=None): self.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder item = {} - if rel is not None: - item['rel'] = rel + if alternate is not None: + item['alternate'] = bool(alternate) if title is not None: item['title'] = title if '://' in filename: diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index 93dc34d57..4e52c3113 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -108,19 +108,19 @@ {%- else %} {%- set filename = cssfile %} {%- endif %} - {%- if cssfile.rel is defined %} - {%- set rel = cssfile.rel %} + {%- if cssfile.alternate is defined %} + {%- set alt = cssfile.alternate %} {%- endif %} {%- if cssfile.title is defined and cssfile.title is string %} - {%- if cssfile.rel is not defined %} - {%- set rel = "alternate stylesheet" %} + {%- if cssfile.alternate is not defined %} + {%- set alt = True %} {%- endif %} - + {%- else %} - {%- if cssfile.rel is not defined %} - {%- set rel = "stylesheet" %} + {%- if cssfile.alternate is not defined %} + {%- set alt = False %} {%- endif %} - + {%- endif %} {%- endfor %} {%- endmacro %} From d86efb91927dfd75cd3d02039a3fe9ede2644ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Fdez=2E=20Galv=C3=A1n?= Date: Tue, 17 Mar 2015 15:57:51 +0100 Subject: [PATCH 04/14] Test for alternate stylesheets --- .../test-stylesheets/_templates/layout.html | 7 +++ tests/roots/test-stylesheets/conf.py | 12 ++++++ tests/roots/test-stylesheets/index.rst | 4 ++ tests/test_build_html.py | 43 +++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 tests/roots/test-stylesheets/_templates/layout.html create mode 100644 tests/roots/test-stylesheets/conf.py create mode 100644 tests/roots/test-stylesheets/index.rst diff --git a/tests/roots/test-stylesheets/_templates/layout.html b/tests/roots/test-stylesheets/_templates/layout.html new file mode 100644 index 000000000..3e561619b --- /dev/null +++ b/tests/roots/test-stylesheets/_templates/layout.html @@ -0,0 +1,7 @@ +{% extends "!layout.html" %} +{% set css_files = css_files + ["_static/more_persistent.css", + {"filename": "_static/more_persistent2.css"}, + {"filename": "_static/more_default.css", "title": "Default", "alternate": False}, + {"filename": "_static/more_alternate1.css", "title": "Alternate"}, + {"filename": "_static/more_alternate2.css", "alternate": True}] %} + diff --git a/tests/roots/test-stylesheets/conf.py b/tests/roots/test-stylesheets/conf.py new file mode 100644 index 000000000..8e072de59 --- /dev/null +++ b/tests/roots/test-stylesheets/conf.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' +html_theme = 'classic' +templates_path = ['_templates'] + +def setup(app): + app.add_stylesheet('persistent.css') + app.add_stylesheet('default.css', title="Default", alternate=False) + app.add_stylesheet('alternate1.css', title="Alternate") + app.add_stylesheet('alternate2.css', alternate=True) + diff --git a/tests/roots/test-stylesheets/index.rst b/tests/roots/test-stylesheets/index.rst new file mode 100644 index 000000000..c5c5766ba --- /dev/null +++ b/tests/roots/test-stylesheets/index.rst @@ -0,0 +1,4 @@ +test-stylesheets +================ + +Lorem ipsum dolor diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 3ee89b72b..adefa5c11 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -919,3 +919,46 @@ def test_numfig_with_secnum_depth(app, status, warning): for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found + +@gen_with_app(buildername='html', testroot='stylesheets') +def test_alternate_stylesheets(app, status, warning): + app.builder.build_all() + + expects = { + 'index.html': [ + (".//link[@href='_static/persistent.css']" + "[@rel='stylesheet']", '', True), + (".//link[@href='_static/default.css']" + "[@rel='stylesheet']" + "[@title='Default']", '', True), + (".//link[@href='_static/alternate1.css']" + "[@rel='alternate stylesheet']" + "[@title='Alternate']", '', True), + (".//link[@href='_static/alternate2.css']" + "[@rel='alternate stylesheet']", '', True), + (".//link[@href='_static/more_persistent.css']" + "[@rel='stylesheet']", '', True), + (".//link[@href='_static/more_persistent2.css']" + "[@rel='stylesheet']", '', True), + (".//link[@href='_static/more_default.css']" + "[@rel='stylesheet']" + "[@title='Default']", '', True), + (".//link[@href='_static/more_alternate1.css']" + "[@rel='alternate stylesheet']" + "[@title='Alternate']", '', True), + (".//link[@href='_static/more_alternate2.css']" + "[@rel='alternate stylesheet']", '', True), + ], + } + + for fname, paths in iteritems(expects): + parser = NslessParser() + parser.entity.update(html_entities.entitydefs) + fp = open(os.path.join(app.outdir, fname), 'rb') + try: + etree = ET.parse(fp, parser) + finally: + fp.close() + + for xpath, check, be_found in paths: + yield check_xpath, etree, fname, xpath, check, be_found From ea219a04edb44eb91ae4b6a5b7275a444595d8f5 Mon Sep 17 00:00:00 2001 From: Jellby Date: Sun, 6 Mar 2016 13:49:57 +0100 Subject: [PATCH 05/14] Move CSS properties to a different variable --- doc/templating.rst | 21 ++++++++------ sphinx/application.py | 13 +++++---- sphinx/builders/html.py | 4 ++- sphinx/themes/basic/layout.html | 28 +++++++++---------- .../test-stylesheets/_templates/layout.html | 12 ++++---- 5 files changed, 41 insertions(+), 37 deletions(-) diff --git a/doc/templating.rst b/doc/templating.rst index 0ab005a8e..26930fde2 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -206,17 +206,20 @@ Overriding works like this:: {% set css_files = css_files + ["_static/mystyle.css"] %} - .. versionchanged:: 1.4 - Optionally, ``alternate`` and/or ``title`` attributes can be provided by - supplying a Python dictionary, in which case the filename is given in the - ``filename`` key:: +.. data:: css_props - {% set css_files = css_files + [{"filename":"_static/mystyle.css", "alternate":False, "title":"Default"}] %} + .. versionadded:: 1.4 - The default is no title and ``alternate=False``, but if only ``title`` is - given, the default is ``alternate=True``. If ``alternate`` is ``True``, it - will be translated to ``rel="alternate stylesheet"``, otherwise it will be - ``rel="stylesheet"``. + An optional dict where you can specify ``alternate`` and/or ``title`` + attributes for the css files. The keys are the css filenames, the values + are dicts themselves: + + {% set _dummy = css_props.update( {"_static/mystyle.css": {"alternate":False, "title":"Default"} }) %} + + The default is no title and ``alternate=False``, but if only ``title`` is + given, the default is ``alternate=True``. If ``alternate`` is ``True``, it + will be translated to ``rel="alternate stylesheet"``, otherwise it will be + ``rel="stylesheet"``. Helper Functions ~~~~~~~~~~~~~~~~ diff --git a/sphinx/application.py b/sphinx/application.py index 4465113d7..0c8450f7a 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -745,16 +745,17 @@ class Sphinx(object): def add_stylesheet(self, filename, alternate=None, title=None): self.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder - item = {} + props = {} if alternate is not None: - item['alternate'] = bool(alternate) + props['alternate'] = bool(alternate) if title is not None: - item['title'] = title + props['title'] = title if '://' in filename: - item['filename'] = filename + fname = filename else: - item['filename'] = posixpath.join('_static', filename) - StandaloneHTMLBuilder.css_files.append(item) + fname = posixpath.join('_static', filename) + StandaloneHTMLBuilder.css_files.append(fname) + StandaloneHTMLBuilder.css_props[fname] = props def add_latex_package(self, packagename, options=None): self.debug('[app] adding latex package: %r', packagename) diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 367e28b8d..76e4106ec 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -84,8 +84,9 @@ class StandaloneHTMLBuilder(Builder): # This is a class attribute because it is mutated by Sphinx.add_javascript. script_files = ['_static/jquery.js', '_static/underscore.js', '_static/doctools.js'] - # Dito for this one. + # Ditto for these ones (Sphinx.add_stylesheet). css_files = [] + css_props = {} default_sidebars = ['localtoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'] @@ -345,6 +346,7 @@ class StandaloneHTMLBuilder(Builder): script_files = self.script_files, language = self.config.language, css_files = self.css_files, + css_props = self.css_props, sphinx_version = __display_version__, style = stylename, rellinks = rellinks, diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index ca856649b..a489a7502 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -102,26 +102,24 @@ {%- macro css() %} + {#- Process the custom css files, with their alternate and title properties if available #} {%- for cssfile in css_files %} - {%- if cssfile.filename is defined %} - {%- set filename = cssfile.filename %} + {%- if css_props[cssfile] is not defined %} + {%- set alt = False %} + {%- set csstitle = undefined %} {%- else %} - {%- set filename = cssfile %} - {%- endif %} - {%- if cssfile.alternate is defined %} - {%- set alt = cssfile.alternate %} - {%- endif %} - {%- if cssfile.title is defined and cssfile.title is string %} - {%- if cssfile.alternate is not defined %} - {%- set alt = True %} + {%- set csstitle = css_props[cssfile].title %} + {%- set alt = (csstitle is defined) %} + {%- if css_props[cssfile].alternate is defined %} + {%- set alt = css_props[cssfile].alternate %} {%- endif %} - + {%- endif %} + {%- if alt %} + {%- set rel = "alternate stylesheet" %} {%- else %} - {%- if cssfile.alternate is not defined %} - {%- set alt = False %} - {%- endif %} - + {%- set rel = "stylesheet" %} {%- endif %} + {%- endfor %} {%- endmacro %} diff --git a/tests/roots/test-stylesheets/_templates/layout.html b/tests/roots/test-stylesheets/_templates/layout.html index 3e561619b..97ade552e 100644 --- a/tests/roots/test-stylesheets/_templates/layout.html +++ b/tests/roots/test-stylesheets/_templates/layout.html @@ -1,7 +1,7 @@ {% extends "!layout.html" %} -{% set css_files = css_files + ["_static/more_persistent.css", - {"filename": "_static/more_persistent2.css"}, - {"filename": "_static/more_default.css", "title": "Default", "alternate": False}, - {"filename": "_static/more_alternate1.css", "title": "Alternate"}, - {"filename": "_static/more_alternate2.css", "alternate": True}] %} - +{% set css_files = css_files + ["_static/more_persistent.css", "_static/more_persistent2.css", "_static/more_default.css", "_static/more_alternate1.css", "_static/more_alternate2.css"] %} +{% set _dummy = css_props.update( + {"_static/more_default.css": {"title": "Default", "alternate": False}, + "_static/more_alternate1.css": {"title": "Alternate"}, + "_static/more_alternate2.css": {"alternate": True} } +) %} From fbc8802dc370acd9eaff5a276a54aca953c4837a Mon Sep 17 00:00:00 2001 From: Jellby Date: Thu, 29 Sep 2016 20:27:35 +0200 Subject: [PATCH 06/14] Remove trailing whitespaces --- tests/test_build_html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index a525d5918..2c77e2532 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1123,7 +1123,7 @@ def test_html_sourcelink_suffix(app, status, warning): assert (app.outdir / '_sources' / 'otherext.foo').exists() assert (app.outdir / '_sources' / 'images.txt').exists() - + @gen_with_app(buildername='html', testroot='stylesheets') def test_alternate_stylesheets(app, status, warning): app.builder.build_all() From f105b737eda0f110561c03db23907be5ec4d9b91 Mon Sep 17 00:00:00 2001 From: Jellby Date: Thu, 29 Sep 2016 20:43:43 +0200 Subject: [PATCH 07/14] Let's see now --- tests/test_build_html.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 2c77e2532..80b31a33d 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1156,13 +1156,9 @@ def test_alternate_stylesheets(app, status, warning): } for fname, paths in iteritems(expects): - parser = NslessParser() - parser.entity.update(html_entities.entitydefs) - fp = open(os.path.join(app.outdir, fname), 'rb') - try: - etree = ET.parse(fp, parser) - finally: - fp.close() + with (app.outdir / fname).open('rb') as fp: + etree = HTML_PARSER.parse(fp) for xpath, check, be_found in paths: yield check_xpath, etree, fname, xpath, check, be_found + From 68cf06a2cefa24fa1ab29b0e31a68cd0ad4f01bd Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 4 Mar 2017 12:14:54 +0100 Subject: [PATCH 08/14] Update version (there's still hope) --- doc/templating.rst | 2 +- tests/test_build_html.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/templating.rst b/doc/templating.rst index 31c312c70..033279406 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -208,7 +208,7 @@ Overriding works like this:: .. data:: css_props - .. versionadded:: 1.4 + .. versionadded:: 1.6 An optional dict where you can specify ``alternate`` and/or ``title`` attributes for the css files. The keys are the css filenames, the values diff --git a/tests/test_build_html.py b/tests/test_build_html.py index c43e7e40e..1e4187fdd 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1192,8 +1192,6 @@ def test_html_inventory(app): "[@rel='alternate stylesheet']", '', True), (".//link[@href='_static/more_persistent.css']" "[@rel='stylesheet']", '', True), - (".//link[@href='_static/more_persistent2.css']" - "[@rel='stylesheet']", '', True), (".//link[@href='_static/more_default.css']" "[@rel='stylesheet']" "[@title='Default']", '', True), From 47d823ef24e27cb02e6cda216a9aec3929180915 Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 4 Mar 2017 12:36:02 +0100 Subject: [PATCH 09/14] Try to correct syntax for type annotation --- sphinx/builders/html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 8d20c49d0..6419fac4c 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -115,7 +115,7 @@ class StandaloneHTMLBuilder(Builder): '_static/doctools.js'] # type: List[unicode] # Ditto for these ones (Sphinx.add_stylesheet). css_files = [] # type: List[unicode] - css_props = {} # type: Dict[unicode, unicode/bool] + css_props = {} # type: Dict[unicode, Union[unicode, bool]] imgpath = None # type: unicode domain_indices = [] # type: List[Tuple[unicode, Type[Index], List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool]] # NOQA From 3171a195bb20dbd7f0809a0f886827488be42b33 Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 4 Mar 2017 12:44:43 +0100 Subject: [PATCH 10/14] again --- sphinx/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/application.py b/sphinx/application.py index 0c1efc35c..c17827839 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -797,7 +797,7 @@ class Sphinx(object): posixpath.join('_static', filename)) def add_stylesheet(self, filename, alternate=None, title=None): - # type: (unicode) -> None + # type: (unicode, unicode, unicode) -> None logger.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder props = {} From d8ff893ebd3e402a9331665fd7e6612ee8a59b5a Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 4 Mar 2017 13:06:35 +0100 Subject: [PATCH 11/14] again --- sphinx/application.py | 2 +- sphinx/builders/html.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index c17827839..dfa8e6e48 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -800,7 +800,7 @@ class Sphinx(object): # type: (unicode, unicode, unicode) -> None logger.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder - props = {} + props = {} # type: Dict[Unicode, Union[Unicode, bool]] if alternate is not None: props['alternate'] = bool(alternate) if title is not None: diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 6419fac4c..19b5e688d 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -115,7 +115,7 @@ class StandaloneHTMLBuilder(Builder): '_static/doctools.js'] # type: List[unicode] # Ditto for these ones (Sphinx.add_stylesheet). css_files = [] # type: List[unicode] - css_props = {} # type: Dict[unicode, Union[unicode, bool]] + css_props = {} # type: Dict[unicode, Dict[unicode, Union[unicode, bool]]] imgpath = None # type: unicode domain_indices = [] # type: List[Tuple[unicode, Type[Index], List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool]] # NOQA From b43ae69e0bf2df36c66e4ce620aa9be5e4ac445f Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 4 Mar 2017 13:24:15 +0100 Subject: [PATCH 12/14] again --- sphinx/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/application.py b/sphinx/application.py index dfa8e6e48..04062a176 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -800,7 +800,7 @@ class Sphinx(object): # type: (unicode, unicode, unicode) -> None logger.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder - props = {} # type: Dict[Unicode, Union[Unicode, bool]] + props = {} # type: Dict[unicode, Union[unicode, bool]] if alternate is not None: props['alternate'] = bool(alternate) if title is not None: From 5f25ade72b78bb189966dba966676a63448df058 Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 4 Mar 2017 13:35:03 +0100 Subject: [PATCH 13/14] again --- sphinx/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/application.py b/sphinx/application.py index 04062a176..2ec7f40ec 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -800,7 +800,7 @@ class Sphinx(object): # type: (unicode, unicode, unicode) -> None logger.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder - props = {} # type: Dict[unicode, Union[unicode, bool]] + props = {} # type: Dict[unicode, Union[unicode, bool]] if alternate is not None: props['alternate'] = bool(alternate) if title is not None: From e59a8028d7a68d0e0d915770764566db5951cb26 Mon Sep 17 00:00:00 2001 From: Jellby Date: Sat, 15 Apr 2017 17:07:33 +0200 Subject: [PATCH 14/14] Rewrite and simplify stylesheet handling Thanks to tk0miya's comment, I learnt one can add stuff to template blocks, that allows a much simpler stylesheet configuration, considering that changes at the template level will be more... well, low-level. Hopefully this is now acceptable. --- doc/extdev/appapi.rst | 6 +++-- doc/templating.rst | 21 ---------------- sphinx/application.py | 23 ++++++++---------- sphinx/builders/html.py | 6 ++--- sphinx/themes/basic/layout.html | 24 +++++-------------- sphinx/themes/scrolls/layout.html | 5 +++- .../test-stylesheets/_templates/layout.html | 13 +++++----- tests/roots/test-stylesheets/conf.py | 4 ++-- tests/test_build_html.py | 6 ++--- 9 files changed, 38 insertions(+), 70 deletions(-) diff --git a/doc/extdev/appapi.rst b/doc/extdev/appapi.rst index f5b9bd4ec..b096bca29 100644 --- a/doc/extdev/appapi.rst +++ b/doc/extdev/appapi.rst @@ -310,9 +310,11 @@ package. .. versionadded:: 1.0 - .. versionchanged:: 1.4 + .. versionchanged:: 1.6 Optional ``alternate`` and/or ``title`` attributes can be supplied with - the *alternate* (of boolean type) and *title* (a string) arguments. + the *alternate* (of boolean type) and *title* (a string) arguments. The + default is no title and *alternate*=``False`` (see `this explanation + `_). .. method:: Sphinx.add_latex_package(packagename, options=None) diff --git a/doc/templating.rst b/doc/templating.rst index 033279406..66f72716b 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -200,27 +200,6 @@ Overriding works like this:: {% set script_files = script_files + ["_static/myscript.js"] %} -.. data:: css_files - - Similar to :data:`script_files`, for CSS files:: - - {% set css_files = css_files + ["_static/mystyle.css"] %} - -.. data:: css_props - - .. versionadded:: 1.6 - - An optional dict where you can specify ``alternate`` and/or ``title`` - attributes for the css files. The keys are the css filenames, the values - are dicts themselves: - - {% set _dummy = css_props.update( {"_static/mystyle.css": {"alternate":False, "title":"Default"} }) %} - - The default is no title and ``alternate=False``, but if only ``title`` is - given, the default is ``alternate=True``. If ``alternate`` is ``True``, it - will be translated to ``rel="alternate stylesheet"``, otherwise it will be - ``rel="stylesheet"``. - Helper Functions ~~~~~~~~~~~~~~~~ diff --git a/sphinx/application.py b/sphinx/application.py index ee0294dc1..7007f068d 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -724,21 +724,18 @@ class Sphinx(object): StandaloneHTMLBuilder.script_files.append( posixpath.join('_static', filename)) - def add_stylesheet(self, filename, alternate=None, title=None): - # type: (unicode, unicode, unicode) -> None + def add_stylesheet(self, filename, alternate=False, title=None): + # type: (unicode, bool, unicode) -> None logger.debug('[app] adding stylesheet: %r', filename) from sphinx.builders.html import StandaloneHTMLBuilder - props = {} # type: Dict[unicode, Union[unicode, bool]] - if alternate is not None: - props['alternate'] = bool(alternate) - if title is not None: - props['title'] = title - if '://' in filename: - fname = filename - else: - fname = posixpath.join('_static', filename) - StandaloneHTMLBuilder.css_files.append(fname) - StandaloneHTMLBuilder.css_props[fname] = props + props = {'rel': 'stylesheet', + 'filename': filename, + 'title': title} # type: Dict[unicode, unicode] + if '://' not in filename: + props['filename'] = posixpath.join('_static', filename) + if alternate: + props['rel'] = 'alternate stylesheet' + StandaloneHTMLBuilder.css_files.append(props) def add_latex_package(self, packagename, options=None): # type: (unicode, unicode) -> None diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index c2a3d1024..7bfce0ad6 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -113,9 +113,8 @@ class StandaloneHTMLBuilder(Builder): # This is a class attribute because it is mutated by Sphinx.add_javascript. script_files = ['_static/jquery.js', '_static/underscore.js', '_static/doctools.js'] # type: List[unicode] - # Ditto for these ones (Sphinx.add_stylesheet). - css_files = [] # type: List[unicode] - css_props = {} # type: Dict[unicode, Dict[unicode, Union[unicode, bool]]] + # Ditto for this one (Sphinx.add_stylesheet). + css_files = [] # type: List[Dict[unicode, unicode]] imgpath = None # type: unicode domain_indices = [] # type: List[Tuple[unicode, Type[Index], List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool]] # NOQA @@ -389,7 +388,6 @@ class StandaloneHTMLBuilder(Builder): script_files = self.script_files, language = self.config.language, css_files = self.css_files, - css_props = self.css_props, sphinx_version = __display_version__, style = stylename, rellinks = rellinks, diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index e6e2b2ba4..4f1d71202 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -105,24 +105,8 @@ {%- macro css() %} - {#- Process the custom css files, with their alternate and title properties if available #} - {%- for cssfile in css_files %} - {%- if css_props[cssfile] is not defined %} - {%- set alt = False %} - {%- set csstitle = undefined %} - {%- else %} - {%- set csstitle = css_props[cssfile].title %} - {%- set alt = (csstitle is defined) %} - {%- if css_props[cssfile].alternate is defined %} - {%- set alt = css_props[cssfile].alternate %} - {%- endif %} - {%- endif %} - {%- if alt %} - {%- set rel = "alternate stylesheet" %} - {%- else %} - {%- set rel = "stylesheet" %} - {%- endif %} - + {%- for css in css_files %} + {%- endfor %} {%- endmacro %} @@ -133,9 +117,13 @@ {%- block htmltitle %} {{ title|striptags|e }}{{ titlesuffix }} {%- endblock %} + {%- block csss %} {{ css() }} + {%- endblock %} {%- if not embedded %} + {%- block scripts %} {{ script() }} + {%- endblock %} {%- if use_opensearch %} +{%- endblock %} {# do not display relbars #} {% block relbar1 %}{% endblock %} {% block relbar2 %}{% endblock %} diff --git a/tests/roots/test-stylesheets/_templates/layout.html b/tests/roots/test-stylesheets/_templates/layout.html index 97ade552e..f9e5a2bc9 100644 --- a/tests/roots/test-stylesheets/_templates/layout.html +++ b/tests/roots/test-stylesheets/_templates/layout.html @@ -1,7 +1,8 @@ {% extends "!layout.html" %} -{% set css_files = css_files + ["_static/more_persistent.css", "_static/more_persistent2.css", "_static/more_default.css", "_static/more_alternate1.css", "_static/more_alternate2.css"] %} -{% set _dummy = css_props.update( - {"_static/more_default.css": {"title": "Default", "alternate": False}, - "_static/more_alternate1.css": {"title": "Alternate"}, - "_static/more_alternate2.css": {"alternate": True} } -) %} +{%- block csss %} + {{ super() }} + + + + +{%- endblock %} diff --git a/tests/roots/test-stylesheets/conf.py b/tests/roots/test-stylesheets/conf.py index 8e072de59..208ca8243 100644 --- a/tests/roots/test-stylesheets/conf.py +++ b/tests/roots/test-stylesheets/conf.py @@ -6,7 +6,7 @@ templates_path = ['_templates'] def setup(app): app.add_stylesheet('persistent.css') - app.add_stylesheet('default.css', title="Default", alternate=False) - app.add_stylesheet('alternate1.css', title="Alternate") + app.add_stylesheet('default.css', title="Default") + app.add_stylesheet('alternate1.css', title="Alternate", alternate=True) app.add_stylesheet('alternate2.css', alternate=True) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 046523a0e..4605629f7 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1181,7 +1181,7 @@ def test_html_inventory(app): 'http://example.com/index.html', 'The basic Sphinx documentation for testing') - + @pytest.mark.sphinx('html', testroot='directives-raw') def test_html_raw_directive(app, status, warning): app.builder.build_all() @@ -1194,8 +1194,8 @@ def test_html_raw_directive(app, status, warning): # with substitution assert '

HTML: abc def ghi

' in result assert '

LaTeX: abc ghi

' in result - - + + @pytest.mark.parametrize("fname,expect", flat_dict({ 'index.html': [ (".//link[@href='_static/persistent.css']"