units or unitsdef packages (or just the \unit command)

223 views
Skip to first unread message

Michael Wild

unread,
Dec 7, 2010, 4:39:25 AM12/7/10
to MathJax Users
Hi all

I'm fairly new to MathJax, so please bear with me...

For my typesetting I would like to use the units package (or
preferably unitdefs which builds on top of units), but from looking at
the existing extensions, implementing a package is a fairly non-
trivial task. For the moment I could live with a custom definition of
the \unit and \unitfrac commands from the units package. However, both
take an optional argument and I can't see how to define a custom macro
in MathJax.Hub.Config.TeX.Macros that takes an optional argument.

The reason I need all of this, is that the HTML is produced from
restructuredText sources. The same sources are used to produce LaTeX
output. In the HTML output I could live with ugly units (and using
surrogates, such as $1\,\textnormal{m}/\textnormal{s}$), but in the
LaTeX output this is just a no-go.

How should I proceed, are there any experiences on working around
this, or some advice on how to implement an extension that provides a
command that can be called like $\unitfrac[1]{m}{s}$ and produces $1\,
\textnormal{m}/\textnormal{s}$?

Thanks

Michael

Davide P. Cervone

unread,
Dec 8, 2010, 11:40:58 AM12/8/10
to mathja...@googlegroups.com
You are right that the TeX.Macros object doesn't provide a method of
defining a macro with an optional argument. MathJax doesn't implement
the low-level TeX commands like \if that would be needed to make use
of optional arguments, so they are not available there. To handle
that, you would need to make a javascript-based extension for the TeX
input jax, and there is no documentation for that at the moment.

Here is one way to do it. Add (or merge) the following TeX block to
your MathJax configuration:

TeX: {
Augment: {
Definitions: {macros: {
unitfrac: "myUnitFrac"
}},
Parse: {prototype: {
myUnitFrac: function (name) {
var n = this.GetBrackets(name),
num = this.GetArgument(name),
den = this.GetArgument(name);
if (n == null) {n = ""}
var tex = n + '\\,\\text{'+num+'}/\\text{'+den+'}';
this.string = tex + this.string.slice(this.i); this.i = 0;
}
}}
}
}

The Definitions.macros section adds a new macro \unitfrac that is tied
to the javascript function called myUnitFrac. That function is
defined in the Parser.prototype section. It receives the name of the
macro that called it (since it can be linked to more than one macro),
and this particular function looks up the optional bracketed argument,
then the numerator and denominator. If there was no bracket argument,
it is null, and we set it to "" (so that we can use it in the next
statement). The tex variable holds the replacement string, and then
it replaces the current string being parsed by the new tex string plus
whatever was left of the old one and sets the current location to the
beginning of the new string. This effectively inserts your
replacement text into the TeX string being parsed.

If you want to put this into a separate extension file, you should
look at something like MathJax/unpacked/extensions/TeX/verb.js for an
example of how that is done.

Note that this does rely on the internals of MathJax's TeX input jax,
and those are subject to change without notice. The use of
this.string and this.i are the only items here that I would worry
about, but I don't expect them to change in the future (but I expect
there should be a method added in the future to do this replacement
rather than doing this by hand).

Of course, a full implementation of the units and unitsdef package
would be more complicated, but this is a starting point.

Davide

Michael Wild

unread,
Dec 8, 2010, 2:52:14 PM12/8/10
to mathja...@googlegroups.com
Perfect, thanks a lot for the hint. Actually, implementing the \unit and
\unitfrac commands is pretty simple (the actuall cls file is very
short), but the associated nicefrac package is more involved. But for
now I can live with "ugly" fractions :-)

Also, isn't this hint something that belongs into the FAQ? I imagine
many people would like to know how to implement custom commands which
take optional arguments...

Michael

pyba

unread,
Dec 20, 2010, 4:17:36 AM12/20/10
to MathJax Users
Hello,
is -it possible to define the following command dinamically in the
HTML code.

Best regards.
Christophe

============================================================

Davide P. Cervone

unread,
Jan 4, 2011, 9:06:38 AM1/4/11
to mathja...@googlegroups.com
Yes, you could use

<SCRIPT>
MathJax.Hub.Register.StartupHook("TeX Jax Ready",function () {
var TEX = MathJax.InputJax.TeX;
TEX.Definitions.macros.unitfrac = "myUnitFrac";
TEX.Parse.Augment({


myUnitFrac: function (name) {
var n = this.GetBrackets(name),
num = this.GetArgument(name),
den = this.GetArgument(name);
if (n == null) {n = ""}
var tex = n + '\\,\\text{'+num+'}/\\text{'+den+'}';
this.string = tex + this.string.slice(this.i); this.i = 0;
}

});
</SCRIPT>

in the HTML after MathJax.js is loaded.

Davide

PS, sorry for the delay in getting back to you. The holidays, and
work on version 1.1 have put me behind in my responses to the user
group.

pyba

unread,
Jan 4, 2011, 2:08:08 PM1/4/11
to MathJax Users
Thanks.

Christophe.
Reply all
Reply to author
Forward
0 new messages