mingrammer / diagrams

:art: Diagram as Code for prototyping cloud system architectures
https://diagrams.mingrammer.com
MIT License
36.82k stars 2.39k forks source link

Icons not included into the resulting svg and as a result can not be imported into the SaaS such as draw.io #8

Open huksley opened 4 years ago

huksley commented 4 years ago

Icons not included into the resulting svg and as a result can not be imported into the SaaS such as draw.io

Hi, thanks, cool project, I was following guides and created example and changed outformat="svg"

However svg generated contains following:

<g id="node5" class="node">
<title>3f42a5b2346adbddd04f3b60e84ea285</title>
<image xlink:href="/Users/test/.local/share/virtualenvs/diag-AzfPdfmQ/lib/python3.7/site-packages/resources/aws/compute/elastic-container-service.png" width="101px" height="101px" preserveAspectRatio="xMinYMin meet" x="310" y="-470.5"/>
<text text-anchor="middle" x="360.5" y="-358.1" font-family="Sans-Serif" font-size="13.00" fill="#2d3436">web3</text>
</g>

I.e. it references icons from filesystem, as a result, when I try to upload this svg to SaaS such as draw.io it results in image being rendered without icons, i.e.

image

Is there any way to embed icons in the resulting SVG?

mingrammer commented 4 years ago

What's your operating system? and how did you install Graphviz?

huksley commented 4 years ago

What's your operating system? and how did you install Graphviz?

MacOS Mojave 10.14.6 I just did brew install graphviz

mingrammer commented 4 years ago

I have a same issue (on macOS catalina). The output svg is dependant on images on the filesystem.

The default renderer of Graphviz seems not to support embedded svg. cairo renderer could solve this problem. But installation is a little complicated on macOS. (can not install the cairo compatible version via brew. We should build Graphviz from source)

I'm thinking of a simpler way to support it.

atkawa7 commented 4 years ago

Building from Source https://medium.com/@scrossoracle/building-graphviz-from-source-on-macos-b6a846d73949

atkawa7 commented 4 years ago

@huksley @mingrammer checkout this library which helps embed images https://github.com/scour-project/scour

staticaland commented 4 years ago

@atkawa7 Thanks! scour works well for me with this code:

from scour import scour
from diagrams import Diagram
from diagrams.aws.compute import EC2

filename = "ec2"
outformat = "svg"
full_filename = f"{filename}.{outformat}"

with Diagram("EC2", filename=filename, show=False, direction="LR", outformat=outformat, graph_attr={"pad": "0.1,0.1"}):
    EC2()

with open(full_filename, "r") as f:

    in_string = f.read()
    out_string = scour.scourString(in_string)

with open(full_filename, "w") as f:

    f.write(out_string)

This embeds the images as base64 in the XML of the SVG file. Of course a better solution would be to intercept the SVG before it's saved to disk.

So instead of running self.dot.render(format=self.outformat, view=self.show) on the SVG, maybe do something like scour.scourString(self.dot.pipe().decode('utf-8')) and write that to file. What do you think @mingrammer?

See https://graphviz.readthedocs.io/en/stable/manual.html#piped-output

Function in scour is embedRasters.

Used like:

for elem in doc.documentElement.getElementsByTagName('image'):
    embedRasters(elem, options)
mingrammer commented 4 years ago

Thank you for introducing the neat library. I'll review the @staticaland's proposal. It sounds good to me.

ajeep8 commented 2 years ago

I make install graphviz with libpango on my ubuntu, and dot -Tsvg:cairo test.gv>test.svg can got svg with icons, but python test.py still output a svg without icons.

Where can I add ":cairo" so python a diagrams file can output svg with icons?

ajeep8 commented 2 years ago

An ugly patch :-D

def __exit__(self, exc_type, exc_value, traceback):
  self.render()
  if self.outformat=="svg":
    os.system("dot -Tsvg:cairo {0} > {0}.svg".format(self.filename))
  os.remove(self.filename)
  setdiagram(None)
iainelder commented 2 years ago

My current project uses Confluence for general documentation and embedded draw.io diagrams for technical illustrations.

The embedded draw.io plugin works well enough, but I hate spending time on laying stuff out by hand.

It would be awesome to be able to generate the layout using this library and import it!

(PS Thanks for making this! I was a fan of graphviz but never had the patience to make it look pretty.)

skgsergio commented 2 years ago

Less ugly patch than the one mentioned by @ajeep8:

with Diagram("My Diagram", show=False, outformat="svg", graph_attr={"bgcolor": "white"}) as diag:
    # Use graphviz cairo renderer to force image embedding
    diag.dot.renderer = "cairo"

"bgcolor": "white" is important if you want a solid white background as using cairo defaults to transparent.

The downside is that it will name your file my_diagram.cairo.svg

srikantviswanath commented 1 month ago

The problem with Cairo as renderer is that it is also encoding link GraphViz attributes like URL, edgeURL and so you lose the intractability of an svg. In my case, that is the main reason to go for svg and hence defeats the purpose.

Any suggestion from someone who ran into similar issue? How are others using URL attributes for e.g.?