Skip to content

Commit

Permalink
[draft] Remove option mathjax_classes
Browse files Browse the repository at this point in the history
The global approach in 395 isn't really sustainable: it requires all-ways
cooperation between all projects that want to customize MathJax.  Additionally,
when processing a MyST document without Sphinx, the MathJax configuration
changes are not performed (part of executablebooks#347).  And, of course, this approach of
overriding the MathJax object causes issues down the line for projects that need
to customize MathJax (the setting in Sphinx isn't sufficient, see sphinx-doc/sphinx#9450)

The following two approaches would not cause these issues:

1. Add a custom script instead of touching the mathjax3_config variable;
   something like this, essentially:

   ```js
   app.add_js_file(None, priority=0, body="""
      var MathJax = window.MathJax || MathJax;
      MathJax.options = MathJax.options || {};
      MathJax.options.processHtmlClass = (MathJax.options.processHtmlClass || "")
      + "|math";
   """)
   ```

- Don't touch MathJax_config at all; instead, add an explicit `mathjax_process`
  class on all math nodes, either by changing `docutils_renderer` (this PR) or by
  adding a Docutils transform to processes all math nodes:

  ```python
  class ActivateMathJaxTransform(Transform):
      default_priority = 800

      @staticmethod
      def is_math(node):
          return isinstance(node, (math, math_block))

      def apply(self, **kwargs):
          for node in self.document.traverse(self.is_math):
              node.attributes.setdefault("classes", []).append("mathjax_process")
  ```

This PR isn't ready for merging; it's just to start a discussion.
  • Loading branch information
cpitclaudel committed Jul 19, 2021
1 parent 5fd4c51 commit 53cfef5
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 66 deletions.
24 changes: 16 additions & 8 deletions myst_parser/docutils_renderer.py
Expand Up @@ -470,6 +470,13 @@ def render_fence(self, token: SyntaxTreeNode) -> None:
self.add_line_and_source_path(node, token)
self.current_node.append(node)

@property
def blocks_mathjax_processing(self):
return self.sphinx_env is None or (
"myst_update_mathjax" in self.sphinx_env.config
and self.sphinx_env.config.myst_update_mathjax
)

def render_heading(self, token: SyntaxTreeNode) -> None:

if self.md_env.get("match_titles", None) is False:
Expand All @@ -490,13 +497,7 @@ def render_heading(self, token: SyntaxTreeNode) -> None:
self.add_line_and_source_path(title_node, token)

new_section = nodes.section()
if level == 1 and (
self.sphinx_env is None
or (
"myst_update_mathjax" in self.sphinx_env.config
and self.sphinx_env.config.myst_update_mathjax
)
):
if level == 1 and self.blocks_mathjax_processing:
new_section["classes"].extend(["tex2jax_ignore", "mathjax_ignore"])
self.add_line_and_source_path(new_section, token)
new_section.append(title_node)
Expand Down Expand Up @@ -775,25 +776,32 @@ def render_table_row(self, token: SyntaxTreeNode) -> None:
with self.current_node_context(para, append=True):
self.render_children(child)

def mark_mathjax_node(self, node):
if self.blocks_mathjax_processing:
node.attributes.setdefault("classes", []).append("mathjax_process")

def render_math_inline(self, token: SyntaxTreeNode) -> None:
content = token.content
if token.markup == "$$":
# available when dmath_double_inline is True
node = nodes.math_block(content, content, nowrap=False, number=None)
else:
node = nodes.math(content, content)
self.mark_mathjax_node(node)
self.add_line_and_source_path(node, token)
self.current_node.append(node)

def render_math_single(self, token: SyntaxTreeNode) -> None:
content = token.content
node = nodes.math(content, content)
node = nodes.math(content, content, classes=["mathjax_process"])
self.mark_mathjax_node(node)
self.add_line_and_source_path(node, token)
self.current_node.append(node)

def render_math_block(self, token: SyntaxTreeNode) -> None:
content = token.content
node = nodes.math_block(content, content, nowrap=False, number=None)
self.mark_mathjax_node(node)
self.add_line_and_source_path(node, token)
self.current_node.append(node)

Expand Down
5 changes: 0 additions & 5 deletions myst_parser/main.py
Expand Up @@ -47,11 +47,6 @@ class MdParserConfig:

update_mathjax: bool = attr.ib(default=True, validator=instance_of(bool))

mathjax_classes: str = attr.ib(
default="tex2jax_process|mathjax_process|math|output_area",
validator=instance_of(str),
)

@enable_extensions.validator
def check_extensions(self, attribute, value):
if not isinstance(value, Iterable):
Expand Down
53 changes: 0 additions & 53 deletions myst_parser/mathjax.py
Expand Up @@ -19,22 +19,6 @@
logger = logging.getLogger(__name__)


def log_override_warning(app: Sphinx, version: int, current: str, new: str) -> None:
"""Log a warning if MathJax configuration being overriden."""
if logging.is_suppressed_warning("myst", "mathjax", app.config.suppress_warnings):
return
config_name = (
"mathjax3_config['options']['processHtmlClass']"
if version == 3
else "mathjax_config['tex2jax']['processClass']"
)
logger.warning(
f"`{config_name}` is being overridden by myst-parser: '{current}' -> '{new}'. "
"Set `suppress_warnings=['myst.mathjax']` to ignore this warning, or "
"`myst_update_mathjax=False` if this is undesirable."
)


def override_mathjax(app: Sphinx):
"""Override aspects of the mathjax extension.
Expand All @@ -51,43 +35,6 @@ def override_mathjax(app: Sphinx):
None,
)

if not app.env.myst_config.update_mathjax: # type: ignore[attr-defined]
return

mjax_classes = app.env.myst_config.mathjax_classes # type: ignore[attr-defined]

if "mathjax3_config" in app.config:
# sphinx 4 + mathjax 3
app.config.mathjax3_config = app.config.mathjax3_config or {} # type: ignore[attr-defined]
app.config.mathjax3_config.setdefault("options", {})
if (
"processHtmlClass" in app.config.mathjax3_config["options"]
and app.config.mathjax3_config["options"]["processHtmlClass"]
!= mjax_classes
):
log_override_warning(
app,
3,
app.config.mathjax3_config["options"]["processHtmlClass"],
mjax_classes,
)
app.config.mathjax3_config["options"]["processHtmlClass"] = mjax_classes
elif "mathjax_config" in app.config:
# sphinx 3 + mathjax 2
app.config.mathjax_config = app.config.mathjax_config or {} # type: ignore[attr-defined]
app.config.mathjax_config.setdefault("tex2jax", {})
if (
"processClass" in app.config.mathjax_config["tex2jax"]
and app.config.mathjax_config["tex2jax"]["processClass"] != mjax_classes
):
log_override_warning(
app,
2,
app.config.mathjax_config["tex2jax"]["processClass"],
mjax_classes,
)
app.config.mathjax_config["tex2jax"]["processClass"] = mjax_classes


def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None:
"""Override for sphinx.ext.mathjax.html_visit_displaymath to handle amsmath.
Expand Down

0 comments on commit 53cfef5

Please sign in to comment.