Hi, commutative diagram \xymatrix does not work in Katex
$$ \xymatrix{
FX \ar[r]^-{Ff} \ar[d]_{\eta_X} & FY \ar[d]^{\eta_Y} \
GX \ar[r]_-{Gf} & GY\} $$
This is very frequently used in mathematics!
@Gwynever Would the AMS {CD} environment be sufficient? {CD} does not supply diagonal arrows, which would make it much, much easier to write than something like \xymatrix or Paul Taylor's package.
A note to other KaTeX contributors: I'm pretty booked up right now and I do not volunteer to make the additions to array.js that would be necessary to parse the {CD} environment. But if someone else takes that on, I can supply SVGs for vertical arrows and edit stretchy.js for the rendering of those arrows.
https://codepen.io/aziis98/pen/KJYqZV
I tried making a prototype of this (at the moment this is all an enormous hack). I wanted to see if it was easily possible to parse the xymatrix syntax and compute all the arrow positions and sizes.
I don't really know if it is possible to create a parser plugin for Katex that does more then adding some simple macros but this may be a starting point.
I tried to comment the code as better as I could. For now I only support simple arrows "->" and double ones "=>" and the support for arrow labels was just too bad to include here (it is commented out).
The parsing part completely bypasses Katex's parsing and macro system (but I think that it might be relatively simple to convert a Katex Macro/Function - for now I just splitting strings and call Katex's "render(expression, node)" on each sub expression)
Probability the most useful part might be the arrow creation. I compute the position of start & end of the arrow and it's angle and then rotate and translate it's container with CSS. For porting to Katex one would just need a function for creating an arrow of given length - I haven't really understood how stretchy.js works (?) for doing this.
Hi @aziis98. This looks really interesting. I noticed that you had some very insightful comments:
// Without the node already in the DOM it looks like
// it doesn't work. Probably because I can't compute
// all the bounding boxes necessary for this to work.
// Tecnically Katex already knows all the bounds
// of its objects (?)
Actually, KaTeX only knows the vertical bounds of all its objects. It relies on the browser to set most horizontal alignment. For fraction bars, KaTeX has always used a span border and a little CSS trickery to make that span width match the width of the numerator and denominator. PR #670 put SVG images of very long arrows into spans with overflow: hidden; and applied the same CSS trickery to make that span width match the subject matter.
The benefit of that approach is that KaTeX never has to query the browser to find the bounds of any of its objects. KaTeX can finish its work and shut down without any cycles of render, measure, render. And this partly explains why KaTeX is fast.
I can think of no CSS trickery that can find the correct geometry for the diagonal arrows in \xymatrix. We either have to settle for the AMS CD package or we have to take your approach and do at least one render, measure cycle.
I'm glad that KaTeX does not have to do render, measure cycles for most math. For the occasional special case, like commutative diagrams, I think it would be okay to use your approach. Then again, that's probably not my call. It would be interesting to hear what others think.
We've always wondered whether we'd need a measurement cycle, but so far @ronkok has proved otherwise. I could see doing such a measurement in an extension, perhaps even a generic "measurement" extension that can callback other extensions. I cannot see doing it in base KaTeX because it's simply incompatible with the renderToString workflow (e.g. server side).
KaTeX could compute an approximate horizontal geometry, as it does have the width of all the characters. Is there any chance that's accurate enough for arrows? I'm guessing @ronkok's thought about this, but could be worth experimenting.
Good point regarding server side rendering. I like the idea of a measurement extension. It could then also support \rotatebox and \cancelto.
Say we wanted a measurement extension. How to go about that? I have some thoughts.
Say we did the following inside KaTeX proper:
Write a series of non-standard unary functions that display stretchy arrows. Give them names like \@rightarrow{<width>}, \@Rightarrow{<width>}, etc. Each function would return a span containing the arrow鈥檚 SVG set inside a box that has a hard width defined. This box would be attached to the baseline.
Write a non-standard \@rotate{<object>}{<angle>}{<width>} function. The object鈥檚 width must be an argument, because many KaTeX objects don鈥檛 know their own width.
Expose a defineTwoStageMacro function, similar to the existing defineMacro function that was used by the mhchem extension, but with an additional callback that would execute after a measurement is taken.
Then the extension would define a macro for \xymatrix that:
Expands into a {array} environment and passes control to KaTeX.
Waits until the first phase is rendered, and takes the necessary measurements of the DOM.
Calculates the geometry for any diagonal arrows and return a revised {array} environment in the callback function. This second set of code would include things like \@rotate{\@rightarrow{2.5em}}{30}{2.5em}
Is this sort of thing feasible?
have there been any updates on this? this is the only thing stopping me from always using KaTeX instead of MathJax!
No progress, I'm afraid. I may take this up after we complete the AMS automatically numbered environments such as equation and align. I don't know when that will occur.
How would you feel about getting the AMS {CD} environment instead of \xymatrix?
The {CD} environment is pretty limited, but better than nothing. I suppose it depends on how much simpler it is to implement than \xymatrix. I really agree with the suggestions above, in that avoiding measurement cycles is great, but the idea of an extension that can be enabled simply for commutative diagrams seems really nice. At the moment, I know of at least one project that uses KaTeX for inline maths, but then loads MathJax for any commutative diagrams, so this sort of special treatment for commutative diagrams is already sort of accepted as a necessity I think.
If we're comparing commutative diagram extensions, supporting tikz-cd (#219) would be even better. I'm not sure what the difficulty of implementation compared to xymatrix would be, though.
This feels like a really complex thing to add and should probably be done as an extension.
As an update to this, AMS's CD environment is now supported in the master branch, thanks to #2396. So you should give that a try! (e.g. on our demo page) Hopefully this suffices for many people's commutative diagrams.
xymatrix could still be a target, so I'll leave this issue open to track that. #219 tracks tikz, but that would be a more major undertaking (and likely a contrib module).
How does one use 'master' on the demo page?
@jedbrown Oops, I was wrong: the demo page uses the official release, not master. (I was confused because the website's documentation is compiled using master, but that's done statically, so there's no live version to play with.) You'll need to build from source and then e.g. yarn start to try out a local demo site -- or install the master branch in your local project.
You can also try out the preview site from the PR which does include the new code in the playground: https://deploy-preview-2396--katex.netlify.app.
Most helpful comment
If we're comparing commutative diagram extensions, supporting
tikz-cd(#219) would be even better. I'm not sure what the difficulty of implementation compared toxymatrixwould be, though.