Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TinyMCE and SVG

Tags:

svg

tinymce

I'm using the latest/current TinyMCE editor (<script type="text/javascript" src='https://cdn.tinymce.com/4/tinymce.min.js'></script>) and it doesn't seem capable of displaying <svg>. I have some HTML saved in a database which contains some <svg>. When loaded in TinyMCE, it doesn't display.

Is this a known issue (I've searched and haven't found much)? Any workarounds?

like image 709
gtilflm Avatar asked Jun 16 '16 14:06

gtilflm


3 Answers

TinyMCE strips empty and invalid tags. You can solve it by

  1. Adding '&nbsp' to each empty element:

    svg.find('*').each(function() {
      if (!$(this).html()) {
        $(this).text('&nbsp;');
      }
    });
    

    here svg is your jQuery wrapped svg element.

  2. Extending the valid elements according to the svg element reference*

    extended_valid_elements: "svg[*],defs[*],pattern[*],desc[*],metadata[*],g[*],mask[*],path[*],line[*],marker[*],rect[*],circle[*],ellipse[*],polygon[*],polyline[*],linearGradient[*],radialGradient[*],stop[*],image[*],view[*],text[*],textPath[*],title[*],tspan[*],glyph[*],symbol[*],switch[*],use[*]"
    

    *Note I added only the elements relevant for my case.

like image 114
Raymundus Avatar answered Oct 29 '22 03:10

Raymundus


Seams to be TinyMCE that removes it because it is an empty tag: http://world.episerver.com/forum/developer-forum/-EPiServer-75-CMS/Thread-Container/2015/1/tinymce-and-svgs/

You might be able to use this inside the init:

extended_valid_elements : "svg[*]",

It works with other empty tags etc, but have never tried with SVG.

From the forum post I linked to:

ok,I did some debugging into TinyMCE and the problem seems to be that the svg element is detected as being empty and therefor removed.

Unfortunatley there is no config way to change this behavior but there are some workarounds.

  1. Always have a name attibute for the svg element: <svg name="something"

  2. Always have a data-mce attribute for the svg element: <svg data-mce-something="something"

  3. Include some text content within the svg element: <svg>&nbsp;</svg> Using these techniques i could succesfully store inline svg in an xhtml property

like image 32
Preben Avatar answered Oct 29 '22 05:10

Preben


I tried Koen's first suggestion and it worked for existing SVG content (I added this in the setup callback). However it still filtered the SVG tags out when pasting HTML into the source code editor and then confirming the dialog.

After digging a bit into TinyMCE's source code to see where those elements are actually removed (it's in the DomParser class) I found an undocumented editor setting for the Schema class that specifies tags that are allowed to be empty without being removed. The only annoying thing is that you can't use it to add to the existing list, you can only override it. So when setting it you have to list the tags it has in there by default as well. Use this in the settings that you provide to TinyMCE when initialising it:

// First the list of tags that it normally knows about by default:
non_empty_elements: "td,th,iframe,video,audio,object,script,pre,code,area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source,wbr,track"
// Now we add tags related to SVGs that it doesn't normally know about:
+ "svg,defs,pattern,desc,metadata,g,mask,path,line,marker,rect,circle,ellipse,polygon,polyline,linearGradient,radialGradient,stop,image,view,text,textPath,title,tspan,glyph,symbol,switch,use",

This way these SVG tags should never be filtered out because they are empty - as long as they are also valid in general, e.g. by setting the extended_valid_elements as Koen suggested above or by allowing all elements (not recommended as it leaves you vulnerable to XSS attacks):

extended_valid_elements: "*[*]"

Please note that this worked for my version 4.5.8 of TinyMCE. Since this setting is undocumented it might not work anymore in current or future versions. Also they might've adjusted the default list that I'm overriding here in later versions. Find nonEmptyElementsMap and shortEndedElementsMap in Schema.js in their source code to find the default list in your version (the two lists get combined) and note that in there the tags are separated by spaces but when you supply a list yourself the list is separated by commas (for whatever reason).

like image 37
Shepard Avatar answered Oct 29 '22 03:10

Shepard