Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default Color #3190

Open
geometrian opened this issue Feb 20, 2024 · 2 comments
Open

Default Color #3190

geometrian opened this issue Feb 20, 2024 · 2 comments
Labels
Code Example Contains an illustrative code example, solution, or work-around Feature Request

Comments

@geometrian
Copy link

I need a way to restore the default color after changing it. One may not know the default color conveniently since it comes from CSS.

In LaTeX, we can restore the default color by doing something like:

\colorlet{colordefl}{.} %save current color
\color{red}
%color is red here
\color{colordefl}
%color is default again

However, \colorlet does not seem to be supported in MathJax. The workaround in most cases is to scope any color changes:

% color is default here
{\color{red}
%color is red here
}
% color is default here again

However, this isn't possible for certain constructs. For example, to color an underbrace and its label, but not its contents:

{\color{red}\
underbrace{\color{colordefl} ...}_{...}
}

This is somewhere between a bug report (\colorlet is missing), a feature request (add it, or equivalent mechanism, please), and a question (how do I do this / is there a workaround?).

@dpvc
Copy link
Member

dpvc commented Feb 23, 2024

The \colorlet macro is from the xcolor LaTeX package, but MathJax v3 implements the color package, not xcolor, which is much more complex. So \colorlet is not part of the MathJax package.

On the other hand, here is a MathJax v3 configuration that implements \colorlet enough to allow you to do what you are asking here.

MathJax = {
  loader: {load: ['[tex]/color']},
  tex: {packages: {'[+]': ['color', 'my-colorlet']}},
  startup: {
    ready() {
      const {Configuration} = MathJax._.input.tex.Configuration;
      const {CommandMap} = MathJax._.input.tex.SymbolMap;
      
      new CommandMap('my-colorlet', {
        colorlet: 'ColorLet'
      }, {
        ColorLet(parser, name) {
          const type = parser.GetBrackets(name);
          const cname = parser.GetArgument(name);
          let model = parser.GetBrackets(name);
          let def = parser.GetArgument(name);
          if (def === '.') {
            if (parser.stack.env.color) {
              def = parser.stack.env.color;
            } else {
              let node = MathJax.config.tex['my-colorlet'].math.start.node.parentNode;
              const style = this.window.getComputedStyle(node);
              def = style.color;
            }
            model = 'named';
          }
          const colorModel = parser.configuration.packageData.get('color').model;
          colorModel.defineColor(model, cname, def);
        }
      });
      
      Configuration.create('my-colorlet', {
        handler: {
          macro: ['my-colorlet']
        },
        config(config, jax) {
          jax.parseOptions.packageData.set('my-colorlet', {jax});           
        }
      });
      
      MathJax.startup.defaultReady();
      
      MathJax.startup.document.inputJax[0].preFilters.add(({math}) => {
        MathJax.config.tex['my-colorlet'] = {math};
      });
    }
  }
};

This handled both colors inherited from the surrounding text, or explicit colors from within the LaTeX. If the color is set via css that targets a sub-element of the expression, this won't pick that up, since the DOM nodes are not built or in the DOM yet at the point that the LaTeX is being processed. To handle that, you would need a more complicated post-processing step in a renderAction that runs after the document-update action.

For the HTML

<div style="color: blue">
  \[
    \colorlet{c1}{.}
    \color{red}\underbrace{\color{c1} x+y+z+w}_{123}
  \]

  \[\color{green}
    \colorlet{c2}{.}
    \color{red}\underbrace{\color{c2} x+y+z+w}_{123}
  \]
</div>

the output is

colorlet

For v4, you can do this simpler configuration that doesn't require modifying MathJax.config, as the current MathItem is stored in the parser.configutation:

MathJax = {
  loader: {load: ['[tex]/color']},
  tex: {packages: {'[+]': ['color', 'my-colorlet']}},
  startup: {
    ready() {
      const {Configuration} = MathJax._.input.tex.Configuration;
      const {CommandMap} = MathJax._.input.tex.TokenMap;
      
      new CommandMap('my-colorlet', {
        colorlet: 'ColorLet'
      }, {
        ColorLet(parser, name) {
          const type = parser.GetBrackets(name);
          const cname = parser.GetArgument(name);
          let model = parser.GetBrackets(name);
          let def = parser.GetArgument(name);
          if (def === '.') {
            if (parser.stack.env.color) {
              def = parser.stack.env.color;
            } else {
              let node = parser.configuration.mathItem.start.node.parentNode;
              const style = this.window.getComputedStyle(node);
              def = style.color;
            }
            model = 'named';
          }
          const colorModel = parser.configuration.packageData.get('color').model;
          colorModel.defineColor(model, cname, def);
        }
      });
      
      Configuration.create('my-colorlet', {
        handler: {
          macro: ['my-colorlet']
        }
      });
      
      MathJax.startup.defaultReady();
    }
  }
};

@dpvc dpvc added the Code Example Contains an illustrative code example, solution, or work-around label Feb 23, 2024
@geometrian
Copy link
Author

This seems like kindof an immense amount of code to accomplish this, though I don't doubt it works, as a workaround. I'll keep with hackish solutions to keep my page load times down; this works well enough for me until native support is added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Code Example Contains an illustrative code example, solution, or work-around Feature Request
Projects
None yet
Development

No branches or pull requests

2 participants