vue.jsvuejs2attributesmathml

Vue replaces "open" attribute to value "open" in any tag


I'm using vue.js (v2.6.12) components in laravel blade templates. For the project, I'm also using MathML in which I need to use the open attribute of <mfenced> tag to be set to some custom values. Here is the example of the math expressing in mathml.

<math xmlns="http://www.w3.org/1998/Math/MathML">
    <mi>f</mi>
    <mfenced close="]" open="[">
        <mrow><mi>a</mi><mo>,</mo><mi>b</mi></mrow>
    </mfenced>
</math>

But as soon as the page renders, the open attribute is converted into this open="open". I'm 100% sure there is no other library or script is loaded that updates like so, just plain vue. This actually breaks the math expression. So it looks like this:

<math xmlns="http://www.w3.org/1998/Math/MathML">
    <mi>f</mi>
    <mfenced close="]" open="open">
        <mrow><mi>a</mi><mo>,</mo><mi>b</mi></mrow>
    </mfenced>
</math>

Later I realized that not only in math expression, litaratily any tag, be it <div open="anything">...</div>, <span open="anything">...</span>, <custom-element open="something">...</custom-element> having open attribute behaves the same. even if I use v-pre attribute to exclude it from vue js templete compiler.

And this do not happen, as soon I disable the vue app initialization.


The question here are:

  1. Why vue is changing the open attribute like so?
  2. How can I stop this behaviour, to the entire page within the vue application area or at least where I choose (something like using v-pre), is there ary config or any other way around?

Solution

  • I've found a simple hack to solve this problem.

    Why hack?

    Because it is eventually going to be fixed in the comming release as pointed by @Michal, so just a quick & dirty hack is enough for now to go for it.

    What I did is I placed the math content in the content and also added it to the data attribute and replacing the original content after vue has done its bad work (sorry just using blade syntax here, but it will make sense). I keep it in both places just for SEO purposes.

    The template where I need math expression to be displayed.

    ...
    <div class="proxy-content" data-proxy-content="{{ $article->content }}">
        {!! $article->content !!}
    </div>
    ...
    

    I was using it along with jQuery, but you can easily substitute with vue.js' $el. This is what it looks in my app.js file.

    ...
    const app = new Vue({
        el: '#app',
    
        methods: {
    
            proxyContent() {
                // Set Proxy Content.
                jQuery('.proxy-content').each((i, el) => {
                    const $el = jQuery(el);
                    $el.html( jQuery('<textarea />').html( $el.data('proxy-content')).text() );
                });
            }
            
            loadMathJax() {
                // Load & Initialize MathJax Library.
                const script = document.createElement("script");
                script.type = "text/javascript";
                script.src  = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";
                document.getElementsByTagName("head")[0].appendChild(script);
            }
    
        }
    
        mounted(){
            // Enable proxy content after mount, so we are sure no more rendering issue for templates.
            this.proxyContent();
    
            // Load MathJax library with a little delay to make sure everything is ready before loading the library.
            setTimeout(() => this.loadMathJax(), 10);
        }
    });
    ...
    

    One might argue, that I'm mixing up things outside of the scope of the vue application. For me that is not an issue, as the whole page is using vue.js and also the single thing don't make any harm even if there is another scope that is using mathml (though it depends on actual implementation).

    In that case, if you want to scope it well, just use $el of vue.