mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x'
This commit is contained in:
commit
a9c7dd7037
2
CHANGES
2
CHANGES
@ -76,6 +76,8 @@ Features added
|
|||||||
value of the variable if docstring contains ``:meta hide-value:`` in
|
value of the variable if docstring contains ``:meta hide-value:`` in
|
||||||
info-field-list
|
info-field-list
|
||||||
* #8619: html: kbd role generates customizable HTML tags for compound keys
|
* #8619: html: kbd role generates customizable HTML tags for compound keys
|
||||||
|
* #8634: html: Allow to change the order of JS/CSS via ``priority`` parameter
|
||||||
|
for :meth:`Sphinx.add_js_file()` and :meth:`Sphinx.add_css_file()`
|
||||||
* #8132: Add :confval:`project_copyright` as an alias of :confval:`copyright`
|
* #8132: Add :confval:`project_copyright` as an alias of :confval:`copyright`
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
|
@ -304,7 +304,7 @@ The following variables available in the templates:
|
|||||||
.. data:: modules
|
.. data:: modules
|
||||||
|
|
||||||
List containing names of "public" modules in the package. Only available for
|
List containing names of "public" modules in the package. Only available for
|
||||||
modules that are packages.
|
modules that are packages and the ``recursive`` option is on.
|
||||||
|
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
@ -911,14 +911,14 @@ class Sphinx:
|
|||||||
"""
|
"""
|
||||||
self.registry.add_post_transform(transform)
|
self.registry.add_post_transform(transform)
|
||||||
|
|
||||||
def add_js_file(self, filename: str, **kwargs: str) -> None:
|
def add_js_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
|
||||||
"""Register a JavaScript file to include in the HTML output.
|
"""Register a JavaScript file to include in the HTML output.
|
||||||
|
|
||||||
Add *filename* to the list of JavaScript files that the default HTML
|
Add *filename* to the list of JavaScript files that the default HTML
|
||||||
template will include. The filename must be relative to the HTML
|
template will include in order of *priority* (ascending). The filename
|
||||||
static path , or a full URI with scheme. If the keyword argument
|
must be relative to the HTML static path , or a full URI with scheme.
|
||||||
``body`` is given, its value will be added between the
|
If the keyword argument ``body`` is given, its value will be added
|
||||||
``<script>`` tags. Extra keyword arguments are included as
|
between the ``<script>`` tags. Extra keyword arguments are included as
|
||||||
attributes of the ``<script>`` tag.
|
attributes of the ``<script>`` tag.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
@ -932,23 +932,38 @@ class Sphinx:
|
|||||||
app.add_js_file(None, body="var myVariable = 'foo';")
|
app.add_js_file(None, body="var myVariable = 'foo';")
|
||||||
# => <script>var myVariable = 'foo';</script>
|
# => <script>var myVariable = 'foo';</script>
|
||||||
|
|
||||||
|
.. list-table:: priority range for JavaScript files
|
||||||
|
:widths: 20,80
|
||||||
|
|
||||||
|
* - Priority
|
||||||
|
- Main purpose in Sphinx
|
||||||
|
* - 200
|
||||||
|
- default priority for built-in JavaScript files
|
||||||
|
* - 500
|
||||||
|
- default priority for extensions
|
||||||
|
* - 800
|
||||||
|
- default priority for :confval:`html_js_files`
|
||||||
|
|
||||||
.. versionadded:: 0.5
|
.. versionadded:: 0.5
|
||||||
|
|
||||||
.. versionchanged:: 1.8
|
.. versionchanged:: 1.8
|
||||||
Renamed from ``app.add_javascript()``.
|
Renamed from ``app.add_javascript()``.
|
||||||
And it allows keyword arguments as attributes of script tag.
|
And it allows keyword arguments as attributes of script tag.
|
||||||
"""
|
|
||||||
self.registry.add_js_file(filename, **kwargs)
|
|
||||||
if hasattr(self.builder, 'add_js_file'):
|
|
||||||
self.builder.add_js_file(filename, **kwargs) # type: ignore
|
|
||||||
|
|
||||||
def add_css_file(self, filename: str, **kwargs: str) -> None:
|
.. versionchanged:: 3.5
|
||||||
|
Take priority argument.
|
||||||
|
"""
|
||||||
|
self.registry.add_js_file(filename, priority=priority, **kwargs)
|
||||||
|
if hasattr(self.builder, 'add_js_file'):
|
||||||
|
self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore
|
||||||
|
|
||||||
|
def add_css_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
|
||||||
"""Register a stylesheet to include in the HTML output.
|
"""Register a stylesheet to include in the HTML output.
|
||||||
|
|
||||||
Add *filename* to the list of CSS files that the default HTML template
|
Add *filename* to the list of CSS files that the default HTML template
|
||||||
will include. The filename must be relative to the HTML static path,
|
will include in order of *priority* (ascending). The filename must be
|
||||||
or a full URI with scheme. The keyword arguments are also accepted for
|
relative to the HTML static path, or a full URI with scheme. The
|
||||||
attributes of ``<link>`` tag.
|
eyword arguments are also accepted for attributes of ``<link>`` tag.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
@ -963,6 +978,16 @@ class Sphinx:
|
|||||||
# => <link rel="alternate stylesheet" href="_static/fancy.css"
|
# => <link rel="alternate stylesheet" href="_static/fancy.css"
|
||||||
# type="text/css" title="fancy" />
|
# type="text/css" title="fancy" />
|
||||||
|
|
||||||
|
.. list-table:: priority range for CSS files
|
||||||
|
:widths: 20,80
|
||||||
|
|
||||||
|
* - Priority
|
||||||
|
- Main purpose in Sphinx
|
||||||
|
* - 500
|
||||||
|
- default priority for extensions
|
||||||
|
* - 800
|
||||||
|
- default priority for :confval:`html_css_files`
|
||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
|
|
||||||
.. versionchanged:: 1.6
|
.. versionchanged:: 1.6
|
||||||
@ -975,11 +1000,14 @@ class Sphinx:
|
|||||||
.. versionchanged:: 1.8
|
.. versionchanged:: 1.8
|
||||||
Renamed from ``app.add_stylesheet()``.
|
Renamed from ``app.add_stylesheet()``.
|
||||||
And it allows keyword arguments as attributes of link tag.
|
And it allows keyword arguments as attributes of link tag.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
Take priority argument.
|
||||||
"""
|
"""
|
||||||
logger.debug('[app] adding stylesheet: %r', filename)
|
logger.debug('[app] adding stylesheet: %r', filename)
|
||||||
self.registry.add_css_files(filename, **kwargs)
|
self.registry.add_css_files(filename, priority=priority, **kwargs)
|
||||||
if hasattr(self.builder, 'add_css_file'):
|
if hasattr(self.builder, 'add_css_file'):
|
||||||
self.builder.add_css_file(filename, **kwargs) # type: ignore
|
self.builder.add_css_file(filename, priority=priority, **kwargs) # type: ignore
|
||||||
|
|
||||||
def add_latex_package(self, packagename: str, options: str = None,
|
def add_latex_package(self, packagename: str, options: str = None,
|
||||||
after_hyperref: bool = False) -> None:
|
after_hyperref: bool = False) -> None:
|
||||||
|
@ -84,10 +84,13 @@ class Stylesheet(str):
|
|||||||
|
|
||||||
attributes = None # type: Dict[str, str]
|
attributes = None # type: Dict[str, str]
|
||||||
filename = None # type: str
|
filename = None # type: str
|
||||||
|
priority = None # type: int
|
||||||
|
|
||||||
def __new__(cls, filename: str, *args: str, **attributes: str) -> "Stylesheet":
|
def __new__(cls, filename: str, *args: str, priority: int = 500, **attributes: Any
|
||||||
|
) -> "Stylesheet":
|
||||||
self = str.__new__(cls, filename) # type: ignore
|
self = str.__new__(cls, filename) # type: ignore
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
self.priority = priority
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
self.attributes.setdefault('rel', 'stylesheet')
|
self.attributes.setdefault('rel', 'stylesheet')
|
||||||
self.attributes.setdefault('type', 'text/css')
|
self.attributes.setdefault('type', 'text/css')
|
||||||
@ -107,10 +110,12 @@ class JavaScript(str):
|
|||||||
|
|
||||||
attributes = None # type: Dict[str, str]
|
attributes = None # type: Dict[str, str]
|
||||||
filename = None # type: str
|
filename = None # type: str
|
||||||
|
priority = None # type: int
|
||||||
|
|
||||||
def __new__(cls, filename: str, **attributes: str) -> "JavaScript":
|
def __new__(cls, filename: str, priority: int = 500, **attributes: str) -> "JavaScript":
|
||||||
self = str.__new__(cls, filename) # type: ignore
|
self = str.__new__(cls, filename) # type: ignore
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
self.priority = priority
|
||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -284,29 +289,31 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
self.add_css_file(filename, **attrs)
|
self.add_css_file(filename, **attrs)
|
||||||
|
|
||||||
for filename, attrs in self.get_builder_config('css_files', 'html'):
|
for filename, attrs in self.get_builder_config('css_files', 'html'):
|
||||||
|
attrs.setdefault('priority', 800) # User's CSSs are loaded after extensions'
|
||||||
self.add_css_file(filename, **attrs)
|
self.add_css_file(filename, **attrs)
|
||||||
|
|
||||||
def add_css_file(self, filename: str, **kwargs: str) -> None:
|
def add_css_file(self, filename: str, **kwargs: Any) -> None:
|
||||||
if '://' not in filename:
|
if '://' not in filename:
|
||||||
filename = posixpath.join('_static', filename)
|
filename = posixpath.join('_static', filename)
|
||||||
|
|
||||||
self.css_files.append(Stylesheet(filename, **kwargs)) # type: ignore
|
self.css_files.append(Stylesheet(filename, **kwargs)) # type: ignore
|
||||||
|
|
||||||
def init_js_files(self) -> None:
|
def init_js_files(self) -> None:
|
||||||
self.add_js_file('jquery.js')
|
self.add_js_file('jquery.js', priority=200)
|
||||||
self.add_js_file('underscore.js')
|
self.add_js_file('underscore.js', priority=200)
|
||||||
self.add_js_file('doctools.js')
|
self.add_js_file('doctools.js', priority=200)
|
||||||
|
|
||||||
for filename, attrs in self.app.registry.js_files:
|
for filename, attrs in self.app.registry.js_files:
|
||||||
self.add_js_file(filename, **attrs)
|
self.add_js_file(filename, **attrs)
|
||||||
|
|
||||||
for filename, attrs in self.get_builder_config('js_files', 'html'):
|
for filename, attrs in self.get_builder_config('js_files', 'html'):
|
||||||
|
attrs.setdefault('priority', 800) # User's JSs are loaded after extensions'
|
||||||
self.add_js_file(filename, **attrs)
|
self.add_js_file(filename, **attrs)
|
||||||
|
|
||||||
if self.config.language and self._get_translations_js():
|
if self.config.language and self._get_translations_js():
|
||||||
self.add_js_file('translations.js')
|
self.add_js_file('translations.js')
|
||||||
|
|
||||||
def add_js_file(self, filename: str, **kwargs: str) -> None:
|
def add_js_file(self, filename: str, **kwargs: Any) -> None:
|
||||||
if filename and '://' not in filename:
|
if filename and '://' not in filename:
|
||||||
filename = posixpath.join('_static', filename)
|
filename = posixpath.join('_static', filename)
|
||||||
|
|
||||||
@ -1009,6 +1016,10 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
if newtmpl:
|
if newtmpl:
|
||||||
templatename = newtmpl
|
templatename = newtmpl
|
||||||
|
|
||||||
|
# sort JS/CSS before rendering HTML
|
||||||
|
ctx['script_files'].sort(key=lambda js: js.priority)
|
||||||
|
ctx['css_files'].sort(key=lambda js: js.priority)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
output = self.templates.render(templatename, ctx)
|
output = self.templates.render(templatename, ctx)
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
|
@ -60,7 +60,7 @@ class SphinxComponentRegistry:
|
|||||||
self.documenters = {} # type: Dict[str, Type[Documenter]]
|
self.documenters = {} # type: Dict[str, Type[Documenter]]
|
||||||
|
|
||||||
#: css_files; a list of tuple of filename and attributes
|
#: css_files; a list of tuple of filename and attributes
|
||||||
self.css_files = [] # type: List[Tuple[str, Dict[str, str]]]
|
self.css_files = [] # type: List[Tuple[str, Dict[str, Any]]]
|
||||||
|
|
||||||
#: domains; a dict of domain name -> domain class
|
#: domains; a dict of domain name -> domain class
|
||||||
self.domains = {} # type: Dict[str, Type[Domain]]
|
self.domains = {} # type: Dict[str, Type[Domain]]
|
||||||
@ -91,7 +91,7 @@ class SphinxComponentRegistry:
|
|||||||
self.html_block_math_renderers = {} # type: Dict[str, Tuple[Callable, Callable]]
|
self.html_block_math_renderers = {} # type: Dict[str, Tuple[Callable, Callable]]
|
||||||
|
|
||||||
#: js_files; list of JS paths or URLs
|
#: js_files; list of JS paths or URLs
|
||||||
self.js_files = [] # type: List[Tuple[str, Dict[str, str]]]
|
self.js_files = [] # type: List[Tuple[str, Dict[str, Any]]]
|
||||||
|
|
||||||
#: LaTeX packages; list of package names and its options
|
#: LaTeX packages; list of package names and its options
|
||||||
self.latex_packages = [] # type: List[Tuple[str, str]]
|
self.latex_packages = [] # type: List[Tuple[str, str]]
|
||||||
@ -358,10 +358,10 @@ class SphinxComponentRegistry:
|
|||||||
attrgetter: Callable[[Any, str, Any], Any]) -> None:
|
attrgetter: Callable[[Any, str, Any], Any]) -> None:
|
||||||
self.autodoc_attrgettrs[typ] = attrgetter
|
self.autodoc_attrgettrs[typ] = attrgetter
|
||||||
|
|
||||||
def add_css_files(self, filename: str, **attributes: str) -> None:
|
def add_css_files(self, filename: str, **attributes: Any) -> None:
|
||||||
self.css_files.append((filename, attributes))
|
self.css_files.append((filename, attributes))
|
||||||
|
|
||||||
def add_js_file(self, filename: str, **attributes: str) -> None:
|
def add_js_file(self, filename: str, **attributes: Any) -> None:
|
||||||
logger.debug('[app] adding js_file: %r, %r', filename, attributes)
|
logger.debug('[app] adding js_file: %r, %r', filename, attributes)
|
||||||
self.js_files.append((filename, attributes))
|
self.js_files.append((filename, attributes))
|
||||||
|
|
||||||
|
@ -1204,6 +1204,35 @@ def test_html_assets(app):
|
|||||||
'</script>' in content)
|
'</script>' in content)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='html_assets')
|
||||||
|
def test_assets_order(app):
|
||||||
|
app.add_css_file('normal.css')
|
||||||
|
app.add_css_file('early.css', priority=100)
|
||||||
|
app.add_css_file('late.css', priority=750)
|
||||||
|
app.add_css_file('lazy.css', priority=900)
|
||||||
|
app.add_js_file('normal.js')
|
||||||
|
app.add_js_file('early.js', priority=100)
|
||||||
|
app.add_js_file('late.js', priority=750)
|
||||||
|
app.add_js_file('lazy.js', priority=900)
|
||||||
|
|
||||||
|
app.builder.build_all()
|
||||||
|
content = (app.outdir / 'index.html').read_text()
|
||||||
|
|
||||||
|
# css_files
|
||||||
|
expected = ['_static/pygments.css', '_static/alabaster.css', '_static/early.css',
|
||||||
|
'_static/normal.css', '_static/late.css', '_static/css/style.css',
|
||||||
|
'https://example.com/custom.css', '_static/lazy.css']
|
||||||
|
pattern = '.*'.join('href="%s"' % f for f in expected)
|
||||||
|
assert re.search(pattern, content, re.S)
|
||||||
|
|
||||||
|
# js_files
|
||||||
|
expected = ['_static/early.js', '_static/jquery.js', '_static/underscore.js',
|
||||||
|
'_static/doctools.js', '_static/normal.js', '_static/late.js',
|
||||||
|
'_static/js/custom.js', 'https://example.com/script.js', '_static/lazy.js']
|
||||||
|
pattern = '.*'.join('src="%s"' % f for f in expected)
|
||||||
|
assert re.search(pattern, content, re.S)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_copy_source': False})
|
@pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_copy_source': False})
|
||||||
def test_html_copy_source(app):
|
def test_html_copy_source(app):
|
||||||
app.builder.build_all()
|
app.builder.build_all()
|
||||||
|
Loading…
Reference in New Issue
Block a user