summaryrefslogtreecommitdiff
path: root/sphinx
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx')
-rw-r--r--sphinx/application.py52
-rw-r--r--sphinx/builders/epub3.py1
-rw-r--r--sphinx/builders/html.py62
-rw-r--r--sphinx/deprecation.py4
-rw-r--r--sphinx/registry.py6
-rw-r--r--sphinx/themes/basic/layout.html4
6 files changed, 110 insertions, 19 deletions
diff --git a/sphinx/application.py b/sphinx/application.py
index c8e06245c..71358ca5d 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -27,7 +27,9 @@ from six.moves import cStringIO
import sphinx
from sphinx import package_dir, locale
from sphinx.config import Config
-from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
+from sphinx.deprecation import (
+ RemovedInSphinx20Warning, RemovedInSphinx30Warning, RemovedInSphinx40Warning
+)
from sphinx.environment import BuildEnvironment
from sphinx.errors import (
ApplicationError, ConfigError, ExtensionError, VersionRequirementError
@@ -1001,13 +1003,27 @@ class Sphinx(object):
StandaloneHTMLBuilder.script_files.append(
posixpath.join('_static', filename))
- def add_stylesheet(self, filename, alternate=False, title=None):
- # type: (unicode, bool, unicode) -> None
+ def add_css_file(self, filename, **kwargs):
+ # type: (unicode, **unicode) -> None
"""Register a stylesheet to include in the HTML output.
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 the HTML static path, or a full URI with scheme.
+ will include. The filename must be relative to the HTML static path,
+ or a full URI with scheme. The keyword arguments are also accepted for
+ attributes of ``<link>`` tag.
+
+ Example::
+
+ app.add_css_file('custom.css')
+ # => <link rel="stylesheet" href="_static/custom.css" type="text/css" />
+
+ app.add_css_file('print.css', media='print')
+ # => <link rel="stylesheet" href="_static/print.css"
+ # type="text/css" media="print" />
+
+ app.add_css_file('fancy.css', rel='alternate stylesheet', title='fancy')
+ # => <link rel="alternate stylesheet" href="_static/fancy.css"
+ # type="text/css" title="fancy" />
.. versionadded:: 1.0
@@ -1017,17 +1033,33 @@ class Sphinx(object):
arguments. The default is no title and *alternate* = ``False``. For
more information, refer to the `documentation
<https://mdn.io/Web/CSS/Alternative_style_sheets>`__.
+
+ .. versionchanged:: 1.8
+ Renamed from ``app.add_stylesheet()``.
+ And it allows keyword arguments as attributes of link tag.
"""
logger.debug('[app] adding stylesheet: %r', filename)
- from sphinx.builders.html import StandaloneHTMLBuilder, Stylesheet
if '://' not in filename:
filename = posixpath.join('_static', filename)
+ self.registry.add_css_files(filename, **kwargs)
+
+ def add_stylesheet(self, filename, alternate=False, title=None):
+ # type: (unicode, bool, unicode) -> None
+ """An alias of :meth:`add_css_file`."""
+ warnings.warn('The app.add_stylesheet() is deprecated. '
+ 'Please use app.add_css_file() instead.',
+ RemovedInSphinx40Warning)
+
+ attributes = {} # type: Dict[unicode, unicode]
if alternate:
- rel = u'alternate stylesheet'
+ attributes['rel'] = 'alternate stylesheet'
else:
- rel = u'stylesheet'
- css = Stylesheet(filename, title, rel) # type: ignore
- StandaloneHTMLBuilder.css_files.append(css)
+ attributes['rel'] = 'stylesheet'
+
+ if title:
+ attributes['title'] = title
+
+ self.add_css_file(filename, **attributes)
def add_latex_package(self, packagename, options=None):
# type: (unicode, unicode) -> None
diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py
index 752a3990d..895d2f5f5 100644
--- a/sphinx/builders/epub3.py
+++ b/sphinx/builders/epub3.py
@@ -247,6 +247,7 @@ def setup(app):
app.add_config_value('epub_guide', (), 'env')
app.add_config_value('epub_pre_files', [], 'env')
app.add_config_value('epub_post_files', [], 'env')
+ app.add_config_value('epub_css_files', lambda config: config.html_css_files, 'epub')
app.add_config_value('epub_exclude_files', [], 'env')
app.add_config_value('epub_tocdepth', 3, 'env')
app.add_config_value('epub_tocdup', True, 'env')
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 257b35353..25538ac17 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -50,6 +50,7 @@ from sphinx.util.matching import patmatch, Matcher, DOTFILES
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
movefile, copyfile
+from sphinx.util.pycompat import htmlescape
from sphinx.writers.html import HTMLWriter, HTMLTranslator
if False:
@@ -101,7 +102,7 @@ class CSSContainer(list):
if isinstance(obj, Stylesheet):
super(CSSContainer, self).append(obj)
else:
- super(CSSContainer, self).append(Stylesheet(obj, None, 'stylesheet')) # type: ignore # NOQA
+ super(CSSContainer, self).append(Stylesheet(obj))
def insert(self, index, obj):
# type: (int, Union[unicode, Stylesheet]) -> None
@@ -111,7 +112,7 @@ class CSSContainer(list):
if isinstance(obj, Stylesheet):
super(CSSContainer, self).insert(index, obj)
else:
- super(CSSContainer, self).insert(index, Stylesheet(obj, None, 'stylesheet')) # type: ignore # NOQA
+ super(CSSContainer, self).insert(index, Stylesheet(obj))
def extend(self, other): # type: ignore
# type: (List[Union[unicode, Stylesheet]]) -> None
@@ -144,12 +145,19 @@ class Stylesheet(text_type):
its filename (str).
"""
- def __new__(cls, filename, title, rel):
+ attributes = None # type: Dict[unicode, unicode]
+ filename = None # type: unicode
+
+ def __new__(cls, filename, *args, **attributes):
# type: (unicode, unicode, unicode) -> None
self = text_type.__new__(cls, filename) # type: ignore
self.filename = filename
- self.title = title
- self.rel = rel
+ 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]
return self
@@ -241,8 +249,6 @@ 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 this one (Sphinx.add_stylesheet).
- css_files = CSSContainer() # 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
@@ -250,6 +256,13 @@ class StandaloneHTMLBuilder(Builder):
# cached publisher object for snippets
_publisher = None
+ def __init__(self, app):
+ # type: (Sphinx) -> None
+ super(StandaloneHTMLBuilder, self).__init__(app)
+
+ # CSS files
+ self.css_files = CSSContainer() # type: List[Dict[unicode, unicode]]
+
def init(self):
# type: () -> None
self.build_info = self.create_build_info()
@@ -262,6 +275,7 @@ class StandaloneHTMLBuilder(Builder):
self.init_templates()
self.init_highlighter()
+ self.init_css_files()
if self.config.html_file_suffix is not None:
self.out_suffix = self.config.html_file_suffix
@@ -324,6 +338,27 @@ class StandaloneHTMLBuilder(Builder):
self.highlighter = PygmentsBridge('html', style,
self.config.trim_doctest_flags)
+ def init_css_files(self):
+ # type: () -> None
+ 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
@@ -988,6 +1023,17 @@ class StandaloneHTMLBuilder(Builder):
return uri
ctx['pathto'] = pathto
+ def css_tag(css):
+ # type: (Stylesheet) -> unicode
+ 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 '<link %s />' % ' '.join(attrs)
+ ctx['css_tag'] = css_tag
+
def hasdoc(name):
# type: (unicode) -> bool
if name in self.env.all_docs:
@@ -1316,6 +1362,7 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
self.templates = None # no template bridge necessary
self.init_templates()
self.init_highlighter()
+ self.init_css_files()
self.use_index = self.get_builder_config('use_index', 'html')
def get_target_uri(self, docname, typ=None):
@@ -1440,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/sphinx/deprecation.py b/sphinx/deprecation.py
index 1b0e862f0..d4067055a 100644
--- a/sphinx/deprecation.py
+++ b/sphinx/deprecation.py
@@ -33,6 +33,10 @@ class RemovedInSphinx30Warning(PendingDeprecationWarning):
pass
+class RemovedInSphinx40Warning(PendingDeprecationWarning):
+ pass
+
+
RemovedInNextVersionWarning = RemovedInSphinx18Warning
diff --git a/sphinx/registry.py b/sphinx/registry.py
index ab4cfce70..dc42219ae 100644
--- a/sphinx/registry.py
+++ b/sphinx/registry.py
@@ -65,6 +65,9 @@ class SphinxComponentRegistry(object):
#: autodoc documenters; a dict of documenter name -> documenter class
self.documenters = {} # type: Dict[unicode, Type[Documenter]]
+ #: css_files; a list of tuple of filename and attributes
+ self.css_files = [] # type: List[Tuple[unicode, Dict[unicode, unicode]]]
+
#: domains; a dict of domain name -> domain class
self.domains = {} # type: Dict[unicode, Type[Domain]]
@@ -412,6 +415,9 @@ class SphinxComponentRegistry(object):
# type: (Type, Callable[[Any, unicode, Any], Any]) -> None
self.autodoc_attrgettrs[typ] = attrgetter
+ def add_css_files(self, filename, **attributes):
+ self.css_files.append((filename, attributes))
+
def add_latex_package(self, name, options):
# type: (unicode, unicode) -> None
logger.debug('[app] adding latex package: %r', name)
diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html
index 68c7d9e51..a25a18b90 100644
--- a/sphinx/themes/basic/layout.html
+++ b/sphinx/themes/basic/layout.html
@@ -97,8 +97,8 @@
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- for css in css_files %}
- {%- if css|attr("rel") %}
- <link rel="{{ css.rel }}" href="{{ pathto(css.filename, 1) }}" type="text/css"{% if css.title is not none %} title="{{ css.title }}"{% endif %} />
+ {%- if css|attr("filename") %}
+ {{ css_tag(css) }}
{%- else %}
<link rel="stylesheet" href="{{ pathto(css, 1) }}" type="text/css" />
{%- endif %}