Merge pull request #10018 from tk0miya/10013_add_async_js_file

Close #10013: html: Allow to change the loading method of JavaScript
This commit is contained in:
Takeshi KOMIYA 2021-12-27 02:30:00 +09:00 committed by GitHub
commit a284aa6571
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 2 deletions

View File

@ -26,6 +26,8 @@ Features added
* #9800: extlinks: Emit warning if a hardcoded link is replaceable * #9800: extlinks: Emit warning if a hardcoded link is replaceable
by an extlink, suggesting a replacement. by an extlink, suggesting a replacement.
* #9961: html: Support nested <kbd> HTML elements in other HTML builders * #9961: html: Support nested <kbd> HTML elements in other HTML builders
* #10013: html: Allow to change the loading method of JS via ``loading_method``
parameter for :meth:`Sphinx.add_js_file()`
* #9815: html theme: Wrap sidebar components in div to allow customizing their * #9815: html theme: Wrap sidebar components in div to allow customizing their
layout via CSS layout via CSS
* #9899: py domain: Allows to specify cross-reference specifier (``.`` and * #9899: py domain: Allows to specify cross-reference specifier (``.`` and

View File

@ -930,7 +930,8 @@ class Sphinx:
""" """
self.registry.add_post_transform(transform) self.registry.add_post_transform(transform)
def add_js_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None: def add_js_file(self, filename: str, priority: int = 500,
loading_method: Optional[str] = None, **kwargs: Any) -> None:
"""Register a JavaScript file to include in the HTML output. """Register a JavaScript file to include in the HTML output.
:param filename: The filename of the JavaScript file. It must be relative to the HTML :param filename: The filename of the JavaScript file. It must be relative to the HTML
@ -942,6 +943,8 @@ class Sphinx:
files" below. If the priority of the JavaScript files it the same files" below. If the priority of the JavaScript files it the same
as others, the JavaScript files will be loaded in order of as others, the JavaScript files will be loaded in order of
registration. registration.
:param loading_method: The loading method of the JavaScript file. ``'async'`` or
``'defer'`` is allowed.
:param kwargs: Extra keyword arguments are included as attributes of the ``<script>`` :param kwargs: Extra keyword arguments are included as attributes of the ``<script>``
tag. A special keyword argument ``body`` is given, its value will be tag. A special keyword argument ``body`` is given, its value will be
added between the ``<script>`` tag. added between the ``<script>`` tag.
@ -951,7 +954,7 @@ class Sphinx:
app.add_js_file('example.js') app.add_js_file('example.js')
# => <script src="_static/example.js"></script> # => <script src="_static/example.js"></script>
app.add_js_file('example.js', async="async") app.add_js_file('example.js', loading_method="async")
# => <script src="_static/example.js" async="async"></script> # => <script src="_static/example.js" async="async"></script>
app.add_js_file(None, body="var myVariable = 'foo';") app.add_js_file(None, body="var myVariable = 'foo';")
@ -980,7 +983,15 @@ class Sphinx:
.. versionchanged:: 3.5 .. versionchanged:: 3.5
Take priority argument. Allow to add a JavaScript file to the specific page. Take priority argument. Allow to add a JavaScript file to the specific page.
.. versionchanged:: 4.4
Take loading_method argument. Allow to change the loading method of the
JavaScript file.
""" """
if loading_method == 'async':
kwargs['async'] = 'async'
elif loading_method == 'defer':
kwargs['defer'] = 'defer'
self.registry.add_js_file(filename, priority=priority, **kwargs) self.registry.add_js_file(filename, priority=priority, **kwargs)
if hasattr(self.builder, 'add_js_file'): if hasattr(self.builder, 'add_js_file'):
self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore

View File

@ -1195,6 +1195,20 @@ def test_assets_order(app):
assert re.search(pattern, content, re.S) assert re.search(pattern, content, re.S)
@pytest.mark.sphinx('html', testroot='html_assets')
def test_javscript_loading_method(app):
app.add_js_file('normal.js')
app.add_js_file('early.js', loading_method='async')
app.add_js_file('late.js', loading_method='defer')
app.builder.build_all()
content = (app.outdir / 'index.html').read_text()
assert '<script src="_static/normal.js"></script>' in content
assert '<script async="async" src="_static/early.js"></script>' in content
assert '<script defer="defer" src="_static/late.js"></script>' in content
@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()