Skip to content

Instantly share code, notes, and snippets.

@kLiHz
Last active May 17, 2022 17:46
Show Gist options
  • Save kLiHz/61ca333fc5242829d9739b5df6548610 to your computer and use it in GitHub Desktop.
Save kLiHz/61ca333fc5242829d9739b5df6548610 to your computer and use it in GitHub Desktop.
About SVG output of diagrams.net

Optimize SVG output of diagrams.net

draw.io, available at https://app.diagrams.net, is an easy-to-use diagramming tool. However, the exporting of *.drawio files needs to be taken care of most of the times.

As for PNG exporting, currently the default setting may generates blurring image. Fortunately, this can be fixed by scaling the diagram into a larger one. 1

As for the SVG, things become a bit complicated.

When user viewing the software exported SVG files in a web browser, everything seems just fine. But when they try importing these SVGs into softwares like Word or Inkscape, users may see a "Viewer does not support full SVG 1.1" (now changed to "Text is not SVG - cannot display") text on their image.

Usually this is because draw.io uses HTML code to markup text (and maybe other items) in textboxes and directly embeds them into SVG's <foreignObject> tags. Unfortunately, these "foreign" HTML code cannot be understood by SVG-specific softwares like Inkscape. So, the dev of draw.io insert a info text to prompt the user when the <foreignObject>s are not supported.

As you can see, it's not that these viewers "not supporting full SVG 1.1", but the SVG file contains non-SVG parts which can't be interpreted by softwares other than web browers.

Actually, it is the SVG code that is foreign to the Web browsers.

As for the fallback, draw.io simply trims these text whether the text is too long or broken into multiple line manually by the user, at least for now.

Workarounds

One current workaround provided by draw.io is that user can manually disable 'Word Wrap' and 'Formatted Text' of all textboxes, and draw.io will produce clean SVG on exporting.

See Why text in exported SVG images may not display correctly (diagrams.net).

There are some relative discussions, which happened at:

Note that after disabling "Word Wrap", user needs to manually break long text into multiple lines. Also, the text's style must be adjusted as a whole in a textbox when "Formatted Text" is disabled.


Since draw.io is easy-to-use, I'm trying to find or develop a solution to get native SVG code from its exported SVG or original .drawio file.

For now, we have these desirable solutions:

  • For simple SVG diagrams (which doesn't contain complex formatted text), just follow the methods mentioned above (or try my silly Python Script below...);
  • Try exporting the SVG to PDF (using web broswers), then use Inkscape to generate SVG from PDF.

The script does:

  • remove <switch> for 'unsupporting' text
  • remove all <foreignObjects>

References

Others

These articles might be useful:

Footnotes

  1. Export a diagram as a higher resolution PNG image : draw.io is becoming diagrams.net

import xml.etree.ElementTree as ET
svgxmlnsuri = 'http://www.w3.org/2000/svg'
ET.register_namespace('', svgxmlnsuri)
ns = {'svgns':svgxmlnsuri}
fname = 'P64-12-3.18a.drawio.svg'
# define custon tree builder
class CustomBuilder(ET.TreeBuilder):
def doctype(self, name, pubid, system):
self.doctypeString = f'<!DOCTYPE {name} PUBLIC "{pubid}" "{system}">\n'
print(self.doctypeString)
target = CustomBuilder()
parser = ET.XMLParser(target=target) # custom parser
# parse
tree = ET.parse(fname, parser=parser)
root = tree.getroot()
# delete 'unsupported' text switch
root.remove(root.find('svgns:switch', ns))
# replace inline font family, if necessary
style = ET.Element('style')
style.text = \
'''
text {
font-family: "Times New Roman", SimSun, sans-serif;
font-size: 12px;
}
'''
# root.insert(0, style)
# Fix lost comment
comment = ET.Comment('This file was generated by diagrams.net')
root.insert(0, comment)
# remove <foreignObject>s
for tg in root.find('svgns:g', ns).findall('svgns:g', ns):
if tg[0].tag == f'{{{ns['svgns']}}}switch':
# move dedicated tag out of switch
tg.append(tg[0][1])
# remove switch
tg.remove(tg[0])
outfilename = 'out.svg'
with open(outfilename, 'w', encoding='utf-8') as f:
xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>\n'
f.write(xml_declaration)
f.write(target.doctypeString)
f.write(ET.tostring(
root, encoding='utf-8',
xml_declaration=False, # Manually write declaration
).decode('utf-8'))
f.write('\n')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment