Reputation: 9687
Can I instruct MathJax to accept more than a basic delimiter pair?
I am using the dollar sign inline delimiter for rendering math on a browser.
This causes problems for text such as 500$ + 200$
which matches the MathJax syntax and gets rendered as math. The commonly recommended approach to avoiding non-math content being rendered as math is to enable processEscapes
.
MathJax = {
tex: {
inlineMath: [ ["$", "$"] ],
processEscapes: true,
},
};
The escaping method requires rewriting all content that is not math syntax. Previous 500$ + 200$
becomes 500\$ + 200\$
. This is not an ideal solution where most content is not math heavy. It is worse when content is code heavy.
This is a coding problem that I would rather not pass onto content authors.
A simple improvement will be to expect all inline math content to be $tidy like this$
, where there is no white-space around the expression. Obsidian and possibly other markdown editors seem to be following this pattern even though it still has it pitfalls.
// This doesn't work, is there a similar approach that works?
inlineMath: [ [/\$(?=[^\s])/, /(?<=[^\s])\$/] ]
This is indeed the delimiter expression I use to enable/disable math rendering on a page basis, as recommended by MathJax. The problem occurs on mixed content where MathJax parses the whole page.
[" $", "$ "], [" $", "$"], ["$", "$ "]
Upvotes: 0
Views: 204
Reputation: 12260
Here is a configuration that will allow you to specify patterns for the delimiters that you provide (while still handling delimiters where you don't supply patterns). The patterns must match the delimiters given in the first two entries of the array, but that is the case for your situation, so it should not be a problem for you. (A more general solution would be possible, but would require more work that you didn't need.)
MathJax = {
tex: {
inlineMath: [
['$', '$', /\$(?=[^\s])/, /(?<=[^\s])\$/], // adds two extra parameters for pattern to use
['\\(', '\\)']
]
},
startup: {
ready() {
const {FindTeX} = MathJax._.input.tex.FindTeX;
const {selectOptionsFromKeys} = MathJax._.util.Options;
//
// Subclass the FindTeX class to handle the delimiter patterns
//
class myFindTeX extends FindTeX {
addPattern(starts, delims, display) {
let [open, close, start, end] = delims;
//
// If the extra patterns are given...
//
if (start && end) {
//
// The patterns are expected as strings, so convert RegExp to strings without surrounding /
//
starts.push(start.toString().slice(1).replace(/\/$/, ''));
this.end[open] = [close, display, this.endPattern(null, end.toString().slice(1).replace(/\/$/, ''))];
} else {
//
// Otherwise do the usual delimiter handling
//
super.addPattern(starts, delims, display);
}
}
}
//
// Make an instance of our FindTeX subclass (with the configured options)
// and tell the TeX input jax to use our subclass
//
const options = selectOptionsFromKeys(MathJax.config.tex, myFindTeX.OPTIONS);
MathJax.config.tex.FindTeX = new myFindTeX(options);
MathJax.startup.defaultReady();
}
}
};
Here, we subclass the FindTeX
class and override the method that saves the data for delimiter matching. It checks to see if the patterns are given, and if so, uses those for pattern matching rather than the original strings (though those are still needed in order to have the opening delimiter be able to locate the closing-delimiter information, and for proper close-delimiter processing).
I think this will do what you are looking for. It could be made into a more formal extension, but since it is relatively short, you can use it this way reasonably easily.
Upvotes: 1