varkor / quiver

A modern commutative diagram editor for the web.
https://q.uiver.app
MIT License
2.37k stars 78 forks source link

SVG export #8

Open varkor opened 4 years ago

varkor commented 4 years ago

Currently, quiver draws arrows using SVG, but makes use of a lot of CSS styling, which is badly supported outside of browsers. This makes it difficult to export a diagram as an SVG. Implementing curved arrows (https://github.com/varkor/quiver/issues/5) is going to require rewriting the arrow rendering and we should make sure to use SVG attributes rather than CSS styles, so that it becomes possible to export the entire diagram as an SVG file.

Being able to export to an image format (rather than just LaTeX) would mean quiver could be used as a standalone commutative diagram editor, rather than something that has to be used in conjunction with LaTeX.

varkor commented 3 years ago

SVG export for arrows should become possible with #5. However, since KaTeX doesn't SVG export yet (https://github.com/KaTeX/KaTeX/issues/375), to support text, another solution will be required (such as using MathJax only for SVG rendering).

jxxcarlson commented 3 years ago

Hello Varkor, I discovered your amazing quiver package a few days while researching ways to support commutative diagrams in minilatex.lamdera.app, something it cannot do at the moment. Two comments below (A) one what I think I can do in the near term and (B) what I would love to do with quiver in the longer (but hopefully not tool long) term. I'd be very interested in your ideas on this, and whether some version of (B) is feasible.

(A) The MiniLaTeX app parses a subset of LaTeX in the client, rendering the resulting syntax tree to html but passing math text on to either KaTeX or MathJax — I've used both at various times. I'm now using KaTeX, since its renderToString performs better in the context of Elm, which is what the app is written in. I should have a workaround soon so that I can continue to use KaTeX for most things, but use MathJax for specific environments as needed, e.g., amscd.

This will help a lot, but of course amscd is limited in what it can do, and I would love to find a way to use quiver. Here is an imaginary scenario, with all sorts of details missing, assuming both SVG and LaTeX output from quiver.

  1. The author uses quiver to construct a beautiful commutative diagram.

  2. The presses a button to export appropriately tagged LaTeX and SVG source code, e.g.

\begin{quiver}
\begin{latex}
<The LaTeX Source>
\end{latex}
\begin{svg}
<The SVG Source>
\end{svg}
\end{quiver}
  1. This text is pasted into the current MiniLaTeX document, which renders the SVG part. If the author later wishes to export the document to standard LaTeX, only the LaTeX part, appropriately tagged, is exported.

Export from MiniLaTeX (a "variant" of LaTeX) to standard LaTeX is a feature that already exists, as is display of SVG source. See, for example this document — you can view it without an account on the app (you will be signed in as guest).

The idea behind the workflow 1-2-3 is to make it as friction-free as possible. This is what I imagine to be possible. If one could make it even better, so much the better.

varkor commented 3 years ago

@jxxcarlson: did you forget to write out the details of (B)? Regarding the first point, I would like to be able to export SVG alongside LaTeX, though it is currently blocked on either KaTeX or using MathJax (hopefully as a temporary solution) for SVG output. I wonder, for your purposes, would output in the form of a <iframe> be suitable (since your app is web-based already)? This would definitely be possible (and could have the additional benefit of being interactive, e.g. pannable and zoomable, if that's desirable) in the shorter term.

AlexanderZeilmann commented 2 years ago

May I ask, what is the reason that the diagram is currently split up into several SVG-Elements, i.e., two per arrow? Putting them in the same SVG element would already be half of what has to be done for SVG support.

For the other half, the labels, we can insert the output of KaTeX in a foreignObject inside of the SVG. There should be no need to wait for SVG support in KaTeX or switching over to MathJax here.

Sorry for the question, but it seems to me that all ingredients for SVG support in quiver are already there. They just have to be combined a little differently.

varkor commented 2 years ago

May I ask, what is the reason that the diagram is currently split up into several SVG-Elements, i.e., two per arrow?

Purely for implementational convenience. This would be relatively easy to change.

For the other half, the labels, we can insert the output of KaTeX in a foreignObject inside of the SVG. There should be no need to wait for SVG support in KaTeX or switching over to MathJax here.

SVGs that make use of foreignObjects (which is currently already what quiver uses for labels) require a web browser to render, because they can contain arbitrary HTML, which defeats the primary purpose of exporting to SVG. Furthermore, KaTeX makes use of several fonts, which would have to be embedded directly within the SVG. Even putting aside for the moment the question of copyright, including these fonts in every image would lead to unnecessarily large file sizes.

AlexanderZeilmann commented 2 years ago

Thank you for your answer 🙂

There are probably many use cases for an SVG export, but I think that viewing the SVG in a browser is the most common one. So a solution that works in web browsers is a good start.

Consider the use case of embedding the quiver-generated SVG in a website. The website is very likely to contain other formulas that are also set using KaTeX. This means, the css and fonts of KaTeX are already loaded on the website. There is no need of embedding the fonts in the SVG. I also expect the file size to be a little smaller than if the SVG contains the symbols as SVG paths.

That said, if all use cases should be covered perfectly, one way of including the formulas will probably not be enough.

varkor commented 2 years ago

There are probably many use cases for an SVG export, but I think that viewing the SVG in a browser is the most common one.

You can already export quiver diagrams for embedding on web pages. Do you have a use case that's not covered by that, but is covered by SVGs?

AlexanderZeilmann commented 2 years ago

Do you mean using iframes? Yes, there are a few reasons against iframes:

Security

Every external dependency I include in my website is a security threat. While this is true for any libraries on my website, these dependencies are only changing when I tell them to. iframes on the other hand are dynamical dependencies that might change every time someone loads the site. I have no control over what gets loaded here. There is an entire zoo of security problems related to iframes I won't detail here.

quiver is currently the only external website I am loading content from and correspondingly the only website that is white-listed in my content security policy. Interestingly, while my content security policy does not allow Google Analytics, it is still loaded because it is loaded from an iframe. This is also relevant for the next point: data protection.

Data Protection

I am not a lawyer, this is only my rough understanding of things.

Every inclusion of a quiver diagram makes a call to Google Analytics. I completely understand that you want to analyze the traffic to your domain, to improve quiver and detect misuse. But, if you are based in the EU like me, according to the General Data Protection Regulation one has to ask the website visitors for consent first. This means for every website hosted in the European Union:

  1. Load the website, except for all content that calls to other services like quiver or Google Analytics
  2. Bring up a pop up that tells users something like: "Hey, I want to include an image of a commutative diagram. For this, I need to call quiver and Google. Are you okay with this?"
  3. Only if the user clicks accept I can include quiver and thus load the diagram.

I'm building my websites in such a way, that I do not have to ask users for their consent. Having to do so only because I want to include a diagram feels a bit off.

This is not some abstract regulation, people are actually getting sued because they included such innocent-looking things as Google Fonts.

Performance

Loading a single quiver diagram currently generates 35 HTTP requests, which is more than the other requests for my website combined. To put numbers on it: Loading a typical page on my website takes roughly 1s. If I include a single quiver diagram it takes 3.5s.

This is already a performance hit, but the fun begins when one includes multiple diagrams. In that case, every asset of quiver (JavaScript, CSS, fonts, SVGs) is loaded for every single diagram separately. There is no sharing of anything. The load times scale accordingly.

Modifications and Styling

When using iframes, I'm am getting the diagram as it is displayed in quiver. It might however be necessary to change the diagram in some way (e.g. draw a box around some nodes, ...) because not every possible use case will be covered by quiver.

This also includes the styling of the diagram. For example, currently the background of the diagram is always white. But this looks odd for sites that implement a dark mode version. There is no possibility to write CSS on my site that changes the display of the contents inside of the iframe.

Interactivity

Each iframe is a little sandbox. Meaning that if I dynamically want to modify the diagram using JavaScript I can't do this because I can not get in the iframe. Similarly, executing code on my website when the user is clicking elements in the iframe is not working, because the events cannot get out of the iframe.

SEO problems

To quote google:

IFrames are sometimes used to display content on web pages. Content displayed via iFrames may not be indexed and available to appear in Google's search results. We recommend that you avoid the use of iFrames to display content.

JavaScript

All my websites work with JavaScript disabled. You get a more performant website with JavaScript, but all the features are there without. quiver requires JavaScript to display content. No JavaScript, no diagram.

Longevity

The iframes solution only works as long as there is a server behind q.uiver.app that serves them under the exact URL I am calling them. This means, that if quiver is down for whatever reason, temporarily or permanent, I am getting no diagrams.

Accessibility concerns

One can find mixed opinions on the internet whether iframes are an accessibility problem or not. However I think it is safe to say that an SVG has fewer problems in this regard.

Offline availability

I am experimenting with making my websites available offline using Progressive Web Apps. It seems that there are ways to make iframes kind of work with PWAs but it is not straightforward. However, I have not looked at this in detail.

Costs for you

Finally, every time my website is opened this creates some traffic on your server. Depending on the pricing structure of your hoster this might now or in future generate costs for you. And I am not super happy about my website generating costs for other people.

All the Problems above are solved by SVGs

To be fair, some of the problems can be solved by including a screenshot of the diagram as PNG, but it does not solve all problems (modifications, styling, interactivity, ...) and introduces all the downsides of raster graphics.

Ericson2314 commented 1 year ago

I felt very clever trying to print to PDF, but it came out as complete garbage. Drat!

tim-kt commented 11 months ago

As a workaround, I've been using https://upmath.me/. It converts LaTeX graphics to SVG, which you can then download. It worked for a simple diagram I've made, I don't know how much it can handle.