diff options
Diffstat (limited to 'sphinx')
-rw-r--r-- | sphinx/application.py | 52 | ||||
-rw-r--r-- | sphinx/builders/epub3.py | 1 | ||||
-rw-r--r-- | sphinx/builders/html.py | 62 | ||||
-rw-r--r-- | sphinx/deprecation.py | 4 | ||||
-rw-r--r-- | sphinx/registry.py | 6 | ||||
-rw-r--r-- | sphinx/themes/basic/layout.html | 4 |
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 %} |