Close #6241: html: Allow to add JS/CSS files to the specific page

Allow to add JS/CSS files to the specific page when an extension calls
`app.add_js_file()` or `app.add_css_file()` on `html-page-context`
event.
This commit is contained in:
Takeshi KOMIYA 2021-01-04 22:23:28 +09:00
parent ac7d574fce
commit af4e615a8a
9 changed files with 49 additions and 13 deletions

View File

@ -22,8 +22,12 @@ Features added
* #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()`
* #6241: html: Allow to add JS/CSS files to the specific page when an extension
calls ``app.add_js_file()`` or ``app.add_css_file()`` on
:event:`html-page-context` event
* #8649: imgconverter: Skip availability check if builder supports the image
type
* #6241: mathjax: Include mathjax.js only on the document using equations
* #8132: Add :confval:`project_copyright` as an alias of :confval:`copyright`
Bugs fixed

View File

@ -369,6 +369,9 @@ Here is a more detailed list of these events.
You can return a string from the handler, it will then replace
``'page.html'`` as the HTML template for this page.
.. note:: You can install JS/CSS files for the specific page via
:meth:`Sphinx.add_js_file` and :meth:`Sphinx.add_css_file` since v3.5.0.
.. versionadded:: 0.4
.. versionchanged:: 1.3

View File

@ -958,6 +958,9 @@ class Sphinx:
* - 800
- default priority for :confval:`html_js_files`
A JavaScript file can be added to the specific HTML page when on extension
calls this method on :event:`html-page-context` event.
.. versionadded:: 0.5
.. versionchanged:: 1.8
@ -965,7 +968,7 @@ class Sphinx:
And it allows keyword arguments as attributes of script tag.
.. versionchanged:: 3.5
Take priority argument.
Take priority argument. Allow to add a JavaScript file to the specific page.
"""
self.registry.add_js_file(filename, priority=priority, **kwargs)
if hasattr(self.builder, 'add_js_file'):
@ -1004,6 +1007,9 @@ class Sphinx:
* - 800
- default priority for :confval:`html_css_files`
A CSS file can be added to the specific HTML page when on extension calls
this method on :event:`html-page-context` event.
.. versionadded:: 1.0
.. versionchanged:: 1.6
@ -1018,7 +1024,7 @@ class Sphinx:
And it allows keyword arguments as attributes of link tag.
.. versionchanged:: 3.5
Take priority argument.
Take priority argument. Allow to add a CSS file to the specific page.
"""
logger.debug('[app] adding stylesheet: %r', filename)
self.registry.add_css_files(filename, priority=priority, **kwargs)

View File

@ -466,6 +466,10 @@ class StandaloneHTMLBuilder(Builder):
rellinks.append((indexname, indexcls.localname,
'', indexcls.shortname))
# back up script_files and css_files to allow adding JS/CSS files to a specific page.
self._script_files = list(self.script_files)
self._css_files = list(self.css_files)
if self.config.html_style is not None:
stylename = self.config.html_style
elif self.theme:
@ -1016,6 +1020,10 @@ class StandaloneHTMLBuilder(Builder):
self.add_sidebars(pagename, ctx)
ctx.update(addctx)
# revert script_files and css_files
self.script_files[:] = self._script_files
self.css_files[:] = self.css_files
self.update_page_context(pagename, templatename, ctx, event_arg)
newtmpl = self.app.emit_firstresult('html-page-context', pagename,
templatename, ctx, event_arg)

View File

@ -157,8 +157,11 @@ class MathDomain(Domain):
targets = [eq for eq in self.equations.values() if eq[0] == docname]
return len(targets) + 1
def has_equations(self) -> bool:
return any(self.data['has_equations'].values())
def has_equations(self, docname: str = None) -> bool:
if docname:
return self.data['has_equations'].get(docname, False)
else:
return any(self.data['has_equations'].values())
def setup(app: "Sphinx") -> Dict[str, Any]:

View File

@ -17,9 +17,7 @@ from docutils import nodes
import sphinx
from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.domains.math import MathDomain
from sphinx.environment import BuildEnvironment
from sphinx.errors import ExtensionError
from sphinx.locale import _
from sphinx.util.math import get_node_equation_number
@ -71,25 +69,25 @@ def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None
raise nodes.SkipNode
def install_mathjax(app: Sphinx, env: BuildEnvironment) -> None:
def install_mathjax(app: Sphinx, pagename: str, templatename: str, context: Dict,
event_arg: Any) -> None:
if app.builder.format != 'html' or app.builder.math_renderer_name != 'mathjax': # type: ignore # NOQA
return
if not app.config.mathjax_path:
raise ExtensionError('mathjax_path config value must be set for the '
'mathjax extension to work')
builder = cast(StandaloneHTMLBuilder, app.builder)
domain = cast(MathDomain, env.get_domain('math'))
if domain.has_equations():
domain = cast(MathDomain, app.env.get_domain('math'))
if domain.has_equations(pagename):
# Enable mathjax only if equations exists
options = {'async': 'async'}
if app.config.mathjax_options:
options.update(app.config.mathjax_options)
builder.add_js_file(app.config.mathjax_path, **options)
app.add_js_file(app.config.mathjax_path, **options) # type: ignore
if app.config.mathjax_config:
body = "MathJax.Hub.Config(%s)" % json.dumps(app.config.mathjax_config)
builder.add_js_file(None, type="text/x-mathjax-config", body=body)
app.add_js_file(None, type="text/x-mathjax-config", body=body)
def setup(app: Sphinx) -> Dict[str, Any]:
@ -102,6 +100,6 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
app.add_config_value('mathjax_config', None, 'html')
app.connect('env-updated', install_mathjax)
app.connect('html-page-context', install_mathjax)
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -6,6 +6,7 @@ Test Math
math
page
nomath
.. math:: a^2+b^2=c^2

View File

View File

@ -15,6 +15,7 @@ import warnings
import pytest
from docutils import nodes
from sphinx.ext.mathjax import MATHJAX_URL
from sphinx.testing.util import assert_node
@ -224,6 +225,18 @@ def test_mathjax_config(app, status, warning):
'</script>' in content)
@pytest.mark.sphinx('html', testroot='ext-math',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_is_installed_only_if_document_having_math(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').read_text()
assert MATHJAX_URL in content
content = (app.outdir / 'nomath.html').read_text()
assert MATHJAX_URL not in content
@pytest.mark.sphinx('html', testroot='basic',
confoverrides={'extensions': ['sphinx.ext.mathjax']})
def test_mathjax_is_not_installed_if_no_equations(app, status, warning):