Thanks for sharing your example.
> but wanted to clarify a few things before I proceed:
>
> * In the experiment above, dynamic content is being rendered. This is
> done by using AsciiMathML to create a math node, then feeding that
> math node to MathJax's queue. Is this the most efficient route, or is
> MathJax just going to flatten the math node to a string then re-parse
> it?
Certainly this route works, and a number of sites do use this
approach. But as you feared, MathJax does flatten it and re-parse it
(using the browsers XML parsing machinery, so it is reasonably fast
compared to parsing the tags by hand in javascript). So no, it is not
the most efficient approach.
It would be better to have an ASCIIMathML input jax -- one that takes
the ASCIIMathML input language and converts it to MathJax's internal
format. Since the internal format is essentially MathML (as
javascript objects), this would not be all that hard. In fact, it I
think it should be possible to combine your ASCIIMathML parser with
(part of) MathJax's MathML input jax to do that. It is something that
has been on my to-do list for a while, but hasn't made it to the top
yet.
> * For static environments, typically the page is processed onload. Is
> there good way to extend MathJax with different pre processors,
> ideally while being able to use the CDN version of MathJax? Once
> again, is having AsciiMath create math nodes an efficient workflow, or
> would there be a better, more direct way for AsciiMath to convert the
> content into a format usable by MathJax?
You can write your own preprocessors, and it would be possible to load
them from a remote source while using the CDN (as though they were
config files). There is a call to register a function as a pre-
processor, which you could use to hook up your own so that it will
become part of the MathJax typesetting process. See the tex2jax,
mml2jax, or jsMath2jax extensions for examples. Your code could
convert the ASCIIMathML input to a MathML string, which you would
insert into a <script type="math/mml"> tag at the location of the
mathematics.
But I don't think a preprocessor is the right way to do this. It
would work, but has the double-processing problem that you pointed
out. An input jax is the right way to do that. That could also
potentially be loaded as a config file (like the ones loaded as part
of the combined configuration file you are using). You could use the
MathML input jax as a starting, since it already converts a <math>
node and its children to the MathJax internal format.
Hope that helps.
Davide
Thank you David!
How soon could we get something in CDN, Davide?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.16 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJOSJm4AAoJEMCi9wxDaNqEzwAH/1s3UGljObwqPk8kbH/emzKd
1EehR1knSjdSBNoBo8g3sr6d0hzBgWyxsIBC7npJTgXUomwnVN/dJrr04LVCjhun
/z1anzMzapk9fIkwECPhoC1xXPwkS5NHmivpdWhwowEd3iO/kJnpgIERqDa9ZNfw
B0cB6P5M7Zy4/rA3TgKDefPWtZTNu1tY7upjTLYF8d7gksQg3rBi1Xcrs9U7ZF8t
hA/F/8KBLV/sRXAXirznEOXTf+wholOFToMSd/g0Dg+XhWbQT1DfDhfxKJmqIthg
IhNnSBFI2mZmtEvNgZ+iQ1U7pCo5eZnabGp6z2i5yzWL1zPBvX2koJM01LpEgCg=
=7Edt
-----END PGP SIGNATURE-----
You made fast work of this, and I'm impressed with the results. As
you say, it needs restructuring (for example, the global variables and
functions would need to be put into the AsciiMath input jax's object,
as you mention, and the pre-processor probably can be simplified).
There also seems to be a problem with the Fractur, Script, and some
other font selections. But this is an excellent start, and well worth
pursuing.
The license may well be a problem. My reading of it (and I certainly
am not a lawyer) is that if modifications are made, it can be used
only in another library that is also LGPL, which MathJax isn't. I
know Peter and will contact him about it to see what he recommends.
It might be possible to package this component separately as LGPL if
nothing else can be worked out.
As for using it with the CDN, that should be able to be done. Here's
how:
Create a file called AsciiMath.js (or some such thing) that you will
place on your own server. Let's say that it is at http://www.myserver.edu/MathJax/AsciiMath.js
(of course, you will change this to suite your situation). Then put
into this file the following lines:
MathJax.Ajax.Preloading(
"[MathJax]/jax/input/AsciiMath/config.js",
"[MathJax]/jax/input/AsciiMath/jax.js",
"[MathJax]/extensions/asciimath2jax.js"
);
and then insert the contents of your config.js, the jax.js and the
ascimath2jax.js files. (I.e., concatenate them to the file containing
the lines above). Then, add
MathJax.Ajax.loadComplete("http://www.myserver.edu/MathJax/
AsciiMath.js");
but use whatever URL you are using for this file. Finally, change the
line
ASCIIMATH.loadComplete("jax.js");
to
MathJax.Callback.Queue(
MathJax.Hub.Register.StartupHook("mml Jax Ready"),
["loadComplete",ASCIIMATH,"jax.js"]
);
in the copy of the jax.js file so that the input jax will not start up
until after the element jax is loaded (which happens later on).
Then put the file in the right place on your server, and call the CDN as
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
extensions: ["asciimath2jax.js"],
jax: ["input/AsciiMath","output/NativeMML"]
});
</script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=http://www.myserver.edu/MathJax/AsciiMath.js
"></script>
I would recommend that you use the MMLorHTMLjs configuration file as
well, rather than explicitly setting the NativeMML output jax, since
that will not work with many browsers. To do that, use
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
config: ["MMLorHTML.js"],
extensions: ["asciimath2jax.js"],
jax: ["input/AsciiMath"]
});
</script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=http://www.myserver.edu/MathJax/AsciiMath.js
"></script>
Anyway, that should do it for you.
Thanks for your work on this!
Davide
As David pointed out, there are licensing issues to be worked out
before anything can be done with this. There are also some structural
issues with the code; David's work is a good first step, but it needs
to be cleaned up a bit before it can become part of MathJax, even if
the licensing can be worked out. I have also noticed at least one
situation that causes an error, so there is a little more work to be
done there as well.
I'm in the process of trying to get version 1.2 together for release
this fall, and there is not much time before I have to go back to
teaching, so most of my effort is going to that. I don't think this
will become part of that release. We are still trying to work out how
to handle external contributions properly, and how to vet them
appropriately. David's work should provide some pressure to push that
process forward.
In the meantime, you can use the process I suggested to David if you
want to use his code unofficially now.
Davide
OK. I haven't looked into the details of how it works, but did note
that you were ending up with empty elements for several of the font
changes (but not for all of them).
> I could use some advice from you or someone else who knows Javascript
> OO stuff, since I haven't done much with it...
> In the code I threw together, all the AsciiMath parser variables and
> functions are wrapped inside the big "(function (ASCIIMATH,BROWSER)
> {", so doesn't that keep them out of the global scope?
I hadn't looked very closely at the code, and so I missed that. You
are right, the closure does avoid the global variable issue that I was
concerned about. But see below.
> Is there a
> particular advantage to attaching the variables and methods to the
> ASCIIMATH object, rather than doing as currently done, or wrapping the
> whole asciimath parser in a closure?
There are two reasons to do it as methods of an object (though neither
is a critical as keeping the global namespace clean, which you have
already done). The first is that the routines and data are NOT
completely inaccessible (as they are in the closure), and so can be
overridden or modified without having to change the input jax itself.
For example, it makes it possible to apply patches to the input jax as
configuration files rather than editing the input jax files, and now
that most people are using the CDN, that is particularly useful, since
they don't have access to modify the original code directly. As an
example, with the TeX input jax, someone complained that \sqrt\frac{a}
{b} gave a parsing error, and so I was able to provide a small patch
that he could include in his configuration that would override the
routine used by \sqrt so that this would work for him. That would not
have been possible if the TeX input jax had used the closure technique
to isolate its internals completely. For your jax, I'm thinking that
the AMsymbols table, for instance, might be something that people
would want to be able to add to, and using the object-oriented
approach, that would be possible, whereas the closure prevents that.
The second reason is that, as an object, your input jax could be
subclassed to provide a similar but modified one. This is less
likely, but still something that has occurred with some of the other
jax (I have done this with output jax for very special purposes).
In any case, it would be good to structure your input jax along the
same lines as the existing ones, if only for consistency.
Hope that makes the issues more clear.
Davide
PS, Peter seems amenable to granting a special license to use the code
in MathJax, though the details haven't been worked out, but it looks
like we will be able to include your jax in the core MathJax
distribution. Very nice!
right click on displayed equation and change output
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.16 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iQEcBAEBAgAGBQJOU8UiAAoJEMCi9wxDaNqEoLoIALAY4an+kvy3hY8pLTU7Vhtf
gKqJbTmSi9hs594b7k4LU6BKRRbrIN+krgEImI2dwXMKpmUol73PsTBIlKQiMH3u
uUjPBhF0Gh+eNIvw1O9PmGmGgI+Ke+puZgDuI+UQtZjXx1P/dOFaH1q70wqzV4oG
6c50ugYHSxTS2FnbGddRpLazsak/z00jZ7S5UMCWGcUB1fT93aJ19xaQvpy5SXGe
wC33qyKKS288Z5Ym6JZdBC/v/ZNHlH9qzFiDVkh30dvHqYsBiYIbPtpv8txNi5z4
OmRp7mTKyqcuR5GMF5miEkqLYtB7CYlfE8LzKaGeeDifKs8ZV+PGDhQWDqN8E+E=
=/i4q
-----END PGP SIGNATURE-----
I understand. I go back to teaching next week myself, so things will
slow down with MathJax for a bit.
I'd like to look more closely at what you have done, and will make
further recommendations about structure after that. It may be that in
order to get the license stuff to work out properly, we need to do it
the way you have done (so that the original code is changed as little
as possible).
Davide
Thanks for the information and details on how you are doing this. It
is nice to see that MathJax is working well with Moodle. I have been
following the discussions on the Moodle forums, and you have certainly
done yeoman service in that respect.
> I would like to modify David's jax/input/AsciiMath/jax.js to use more
> symbols that are supported by MathJax and basicly I could of course
> simply add new symbols to var AMsymbols = [...] in that file
One of my concerns about that current arrangement is that this is not
easy to do via configuration parameters. It is certainly something
that would be nice to be able to do.
> it would be nice to be able to use php files to add configurable
> settings
> to mathjax files as well - is it possible to use php files instead of
> js files or does mathjax always use a standard structure to render
> input/output javascript only files?
I'm not certain I understand the question. Are you asking that
MathJax load its components from a .php file so that the contents of
those file can be generated on the fly by php? I don't understand
what you mean by "use a standard structure to render input/output
javascript only files". Certainly MathJax is set up to load
javascript files when it needs to include additional functionality. I
do not think it is necessary to make these be generated by php,
because MathJax already has methods of modifying its configuration
(and even its code) via the configuration blocks like you have already
used. You can use php to include such configuration in your main file
(as you have done already), and that could whatever modifications you
need for the components of MathJax, in general. (The structure of the
current asciimath implementation prevents this, but it is one of the
things I have suggested be changed about it).
Anyway, I may be misunderstanding your request, but I think the needed
functionality is already available.
> One workaround is of course to use modified local files like
> "localasciimath2jax.js" but ideally I would like to allow moodle users
> to select if they want to use files from CDN or local files
I agree, making locally modified versions of the MathJax files isn't
the way to go.
Davide
It looks to me like you have used the wrong version of the David's
asciimath code (and it is David Lippman, not David McCain). There is
a version that implements asciimath as an input jax for MathJax, and
includes an asciimath preprocessor to locate the backtics (see http://dlippman.imathas.com/asciimathjax/)
. That is the one you want, and if you use it, you can just use
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
when you want the page to be processed again. I gave instructions at
http://groups.google.com/group/mathjax-users/msg/704b16901f51ccb3?hl=en
how to package this up for use with the CDN copy of MathJax if you
want to do that rather than host your own installation.
In any case, that should do what you need.
Davide
Davide