Katex: Feature Request: Allow to render to any virtual dom implementation using hyperscript

Created on 25 Jan 2019  路  8Comments  路  Source: KaTeX/KaTeX

The point of this feature request is to allow better integration of KaTeX inside virtual dom libraries like : React, Preact, Vue.js, Hast, Inferno, Snabbdom.... (many more)

Each of these lib basically support an hyperscript implementation to create their flavour of virtual dom :

This feature would be a new method taking an hyperscript implementation like :

/**
 * @param {string} expr - the expression to render
 * @param {object} options - katex rendering options
 * @param {function} h - an hyperscript implementation
 * @return {object} - a (virtual) dom tree
 */
katex.renderToVTree(expr, options, h);

Without this integration, there are many known issues :

  • Right now a library like rehype-katex has to render katex nodes to strings and to reparse them to integrate in their virtual dom implementation (HAST).
  • Many markdown editors that support KaTeX are unable to render the preview with the minimal amount of DOM modification needed, which usually results in preview content being discarded/recreated at each keystroke in the editor.
code cleanup discussion enhancement

All 8 comments

I have a PR ready (not pushed yet because i still need help regarding the test page).
Tell me if anyone is interested

I'm unfamiliar with hyperscript. Is it a compatible intermediate layer supported by all those systems? Should we be switching to it instead of our own internal DOM representation, as returned by katex.__renderToDomTree? (And does katex.__renderToDomTree suffice for your purposes? I believe it was added for roughly this reason.)

@edemaine I recently faced same task (did rendering Katex to virtual DOM) and I want to warn you that it is _not_ compatible layer because h implementations have different interfaces. They accept attributes, SVG namespace, style and whatnot differently. Original hyperscript interface which everyone follows is not complete (does not include attribues and SVG so people implement it as they wish) and I believe you cannot have one implementation for all.

@spontaliku-softaria : thank you for this pertinent remark !
You're mostly right : there are some importants variations to consider in the implementation of the hyperscript DSL.

Some flavours of hyperscript support the extended (Emmet-like) tagname syntax, like in the following example :

h('#id.class1.class2') 
<=> h('div', { className: 'class1 class2', id: 'id'})

Some of them identify the SVG tags while some other offer a specific hyperscript variant for SVG or support a special namespace attribute :

h('path', {d : 'M 0 0 L 10 10'}) 
<=> svg('path', {d : 'M 0 0 L 10 10'}) 
<=> h('path', {d : 'M 0 0 L 10 10', namespace: 'http://www.w3.org/2000/svg'})

And finally, some implementations allow for a varying signature where arguments are recognized by their type, when not on their expected position :

h('div', 'some text')
<=> h('div', {}, ['some text'])

However, i have found that there is some valid ground for a common form that is accepted by almost every implementations and it is the following one :

h(tagName : String!, properties: Object!, children: [String|hNode]!)

Where

  • _all_ three parameters are expected in their respective positions and not null or undefined,
  • className and class should be both set as a string property that accepts a space separated list of class names
  • namespace="http://www.w3.org/2000/svg" should be added to the properties object to create a SVG node.

It's not perfect (there are still problems occuring on the attributes of the style property as to whether they should be camelCased or kebab-cased) but it allready gives us a good 80/20 ratio : 20% of efforts for ~ 80% support on every hyperscript library.

Now.. that could be the moment to propose a Level 1 and Level 2 specification for hyperscript along with a test suite, and see the implementations converge, but it is another story... :)

@edemaine : Thanks a lot for your interest ! :)
There is no need to internally use an hyperscript variant to construct the nodes.. (even if it may allow for some better internal code re-use, but it would be a lot of refactoring)
I'm only proposing to add this new method to export the inner KaTeX DOM representation to any other representation using an hyperscript API. And.. it means to add this method to any VNode.

I have a PR in progress, and it allready gives some pretty good results converting to React, Preact and Inferno, but i need now to figure how i will modify the test page without annoying everybody with this feature that is not central to the main purpose of KaTeX, because the test involve loading every external libraries and rendering them side by side...

@zipang Would this make sense as a module in contrib? (Or as a separate project altogether?) Then you can make a new test page, no need to modify the existing one.

There was a similar request to have buildHTML output HAST, see #800. I think having buildHTML output something that is easily consumable by other tools would be good to have. I don't think that KaTeX needs to define its own DOM representation. As long as style is an object I think we're okay. In terms of adding a new representation, that feels like a short term solution. Long term, if we're outputting some version of HAST we may as well use it internally as well. It's probably easier adding it as a new additional format first and then migrating to use it internally as a separate PR.

I think we should make renderToVTree private though as eventually I think we'll want it to replace __renderToDomTree which will hopefully get promoted to an official API someday.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pvnr0082t picture pvnr0082t  路  4Comments

msridhar picture msridhar  路  3Comments

oddhack picture oddhack  路  3Comments

OisinMoran picture OisinMoran  路  4Comments

HughGrovesArup picture HughGrovesArup  路  4Comments