asciidoctor-diagram icon indicating copy to clipboard operation
asciidoctor-diagram copied to clipboard

Is there a way to integrate asciidoctor with draw.io

Open carun opened this issue 5 years ago • 24 comments

Draw.io diagrams can be saved as XML. Is there a way integrate it with asciidoctor? We can have the drawing power with draw.io as well as automated document generation.

carun avatar Feb 04 '19 18:02 carun

This came from https://github.com/asciidoctor/asciidoctor/issues/3039

carun avatar Feb 04 '19 18:02 carun

How do you envision this integration? Should the XML be sent to the web service for rendering? Or should the offline desktop app be used? Either way, I'm not sure how practical this will be. The exported XML is not really human editable afaict, so there seems to be little advantage compared to exporting an SVG and including that.

FYI, the closest precedent for integrating a remote service like this is an old PR requesting cacoo integration.

pepijnve avatar Feb 05 '19 08:02 pepijnve

It would be nice indeed to have this integration. I think it should work the same way Attlassian Confluence integrates draw io.

mehdichara avatar Mar 22 '19 14:03 mehdichara

@mehdichara could you expand on what that means exactly? How does the Confluence/Draw.io integration work?

pepijnve avatar Mar 22 '19 15:03 pepijnve

draw.io is a client-side app only. It's not a server-based rendering, like PlantUML, for example.

As as SaaS site, draw.io doesn't store anything, it only use third-party storage options.

The XML format is compressed, but it's trivial to inflate it back to a human-readable form, but it's not as compact as PlantUML, the styling and positioning information add a lot of bulk.

The way the Confluence Cloud integration works, and this is probably the simplest way to integration, is to load draw.io as an iFrame and use the postMessage protocol we have to send data to the child frame and back when it's saved, see https://support.draw.io/pages/viewpage.action?pageId=8945851 , https://github.com/jgraph/drawio-html5 and https://desk.draw.io/support/solutions/articles/16000042544-how-does-embed-mode-work- .

That said, this tool, which I'm not familiar with, looks like a server-side compile step tool, and is somewhat better suited to tool designed to fit into such a flow, such as PlantUML.

It you had to try this, there is a Puppeteer based image export repo, https://github.com/jgraph/draw-image-export2, which, given a diagram, will return an image/PDF with various options. However, it's designed to be used as-is with draw.io. To use it on it's own you'd have to dig through the calling code in the main draw repo to work out what to send it.

davidjgraph avatar May 16 '19 09:05 davidjgraph

I would be also interested by this feature.

We are starting to use draw.io for our diagrams, because we want/need the flexibility to style and arrange the diagram with some UI.


The XML format is compressed, but it's trivial to inflate it back to a human-readable form

Yes absolutely. I wrote a small note about the process and I think I will write a script that ensures that the files stays in their decompressed form in our git repository.


Next step for me: investigate how the rendering can be performed from a command-line tool or from a java process. The second case would be great for me, because it would mean we can integrate this as part of asciidoctorj-diagram.

jmini avatar Aug 01 '19 10:08 jmini

You can also add:

compressed="false"

to the file to stop compression. https://video.twimg.com/tweet_video/D_1QQ15X4AAZyVs.mp4

davidjgraph avatar Aug 01 '19 10:08 davidjgraph

I'm not objecting to this, but I still don't see how this would integrate in an asciidoctor workflow exactly. At the moment the diagram extension is focused on converting listing or literal blocks into image blocks. I might be mistaken, but any form of draw.io embedding seems to require generating an iframe. There's nothing wrong with that, but that just doesn't fit well in the current architecture of the extension. @mojavelinux do you know of any precedents for this type of integration? Any suggestions on what the best approach to implement this would be?

pepijnve avatar Aug 01 '19 12:08 pepijnve

I agree, this feels like a different extension. Asciidoctor Diagram is really targetted at ASCII-based diagramming. While draw.io also makes images, it's not the same paradigm. It's more like embedding a gist into a document. Asciidoctor extensions can certainly handle that requirement (see https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/master/lib/gist-block-macro/extension.rb), just not this extension I'd say.

mojavelinux avatar Aug 02 '19 06:08 mojavelinux

Drawio has a command line tool: https://j2r2b.github.io/2019/08/06/drawio-cli.html

It can produce svg, pdf, png or jpeg file.

I agree with you that the syntax to write one diagram is more XML:

This is some text and a diagram:

[drawio]
----
<mxGraphModel dx="1106" dy="776" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="413" pageHeight="583" math="0" shadow="0">
  <root>
    <mxCell id="0" />
    <mxCell id="1" parent="0" />
    <mxCell id="IgmaPHdbTIZ3v5u-N69z-1" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
      <mxGeometry x="20" y="10" width="80" height="40" as="geometry" />
    </mxCell>
    <mxCell id="IgmaPHdbTIZ3v5u-N69z-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="IgmaPHdbTIZ3v5u-N69z-3" target="IgmaPHdbTIZ3v5u-N69z-5">
      <mxGeometry relative="1" as="geometry" />
    </mxCell>
    <mxCell id="IgmaPHdbTIZ3v5u-N69z-3" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" vertex="1" parent="1">
      <mxGeometry x="141" y="10" width="80" height="40" as="geometry" />
    </mxCell>
    <mxCell id="IgmaPHdbTIZ3v5u-N69z-4" value="" style="endArrow=classic;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" edge="1" parent="1" source="IgmaPHdbTIZ3v5u-N69z-1" target="IgmaPHdbTIZ3v5u-N69z-3">
      <mxGeometry width="50" height="50" relative="1" as="geometry">
        <mxPoint x="21" y="118" as="sourcePoint" />
        <mxPoint x="71" y="68" as="targetPoint" />
      </mxGeometry>
    </mxCell>
    <mxCell id="IgmaPHdbTIZ3v5u-N69z-5" value="" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
      <mxGeometry x="262" y="10" width="80" height="40" as="geometry" />
    </mxCell>
  </root>
</mxGraphModel>
----

And I expect people to use the diagram stored in *.drawio file instead of directly in the bloc (but this is also supported by asciidoctor-diagram)

I understand that the content being xml is not exactly the philosophy of asciidoctor-diagram. But all the rest (output format, hashing content to create the file name, ...) would be exactly the same.

jmini avatar Aug 06 '19 05:08 jmini

Thanks for the clarification.

If we consider Asciidoctor Diagram to be a diagram creating tool from a source format, where the less visual input formats will be sourced from a file, then I could see how this could fit into the framework.

mojavelinux avatar Aug 06 '19 05:08 mojavelinux

When you export a diagram in draw.io, there's an Include a copy of my diagram option. Exporting a visual format file, say .png, with this option checked allows you to then open that .png with draw.io (cloud or desktop) in the edit mode, so no need to keep the .drawio file.

This way you don't have to mess around exporting XMLs, putting them in your source code, and keeping the .drawio file. You can simply reference your image in your .adoc file as usual, keeping your code concise while having your diagrams editable.

hunch7 avatar Jan 15 '20 16:01 hunch7

@hunch7 this is a really elegant solution, thank you for sharing

eidottermihi avatar Jan 24 '20 14:01 eidottermihi

This is possible and keeps the .drawio extension:

image::foo.drawio[format=svg,opts=inline]

jgroom33 avatar Mar 19 '20 23:03 jgroom33

This is possible and keeps the .drawio extension:

image::foo.drawio[format=svg,opts=inline]

What I usually do is to prepend .drawio to the extension.

So the file would be named foo.drawio.png.

This way I see immediately that this is a png which is supposed to be edited with drawio.

bachp avatar Apr 27 '20 12:04 bachp

Unless there's a problem with drawio using svg as the source, I think @jgroom33 's answer is the correct solution and works right now without any changes. Basically, drawio is just a nice svg editor and asciidoctor already supports rendering svg, so we shouldn't need anymore integration than that. If you're using vscode, you can use the drawio extension .

  1. create a diagram.drawio.svg file.
  2. Edit and save it with drawio extension
  3. include it in adoc with image::diagram.drawio.svg[format=svg]
  4. preview adoc with adoc extension
  5. Profit

The only problem I'm experiencing with this currently is that if I already have the preview open and edit the diagram, it doesn't always update in the preview, but that's an issue with the vscode extension. I don't think there's any more features that needs to be added to asciidoctor-diagram.

BrendanBall avatar Aug 12 '20 14:08 BrendanBall

Hi

Draw,io supports ascii based diagram description language just like PlantUML. Here are some examples https://github.com/jgraph/drawio-diagrams/tree/master/examples/csv Refer here for how this CSV can be imported https://drawio-app.com/import-from-csv-to-drawio/

I am NOT exactly sure how the integration can work. But since they also support a command-line there may be a possibility of integration here.

Draw.io is differentiates itself from PlantUML by supporting object based diagramming model, where all the UML objects in the diagram can be re-positioned in the UI, unlike PlantUML where we have a fixed SVG or a JPEG

kvanapal avatar Aug 13 '20 18:08 kvanapal

There’s quite a few ways to integrate drawio into a third party system but none really seem to fit the needs that myself and my organisation personally have. Specifically, I’d love to embed drawio diagrams (preferably from the .drawio XML format) but be able to specify layer and page filters. An example of how this might be incredibly powerful is showing multiple perspectives of the same concept which is described using layers toggled on/off from a single diagram. In my specific case, I have a number of diagrams that show security controls overlayed on a base network diagram. Certain sections of my document need to show a different perspective with different controls. One view might be the base layer with enforcement points, like firewalls and security groups. Another would be the same base layer with encryption points. There could be 30 different diagrams all constructed from the same drawio file just toggling different layers or viewing a different page. Every time the diagram changes it may require moving some elements around which means updating all other diagrams in the document by reexporting to svg. If every diagram was unique and had no shared resources then this is no big deal. Export to embedded svg/png and your done. What I need is one source diagram rendered multiple different ways. Also, need them to be rendered in PDF or HTML.

In my mind, this might look like:

.Enforcement Points image::diagram.drawio#page[layers “id1, id2, id3”, other_props...]

.Log and Auditing Controls image::diagram.drawio#page[layers “id1, id9”, other_props...]

Embedded drawio with editing functionality would be a nice future goal but initially I could see this working by writing an extension which just dumps the drawio filtered diagram into a base64 encoded inline image directly into body for HTML backends.

<img style='display:block; width:100px;height:100px;' id='base64image'                 
       src='data:image/jpeg;base64, LzlqLzRBQ...<!-- base64 data -->' />

Similarly for PDF it would just be the image rendered directly into the document.

It does occur to me that svg actually have the concept of layers built into the specification directly. Thus layer visibility can be controlled by dynamically setting the visibility of group elements. Which again, could be done whilst converting a .drawio diagram to svg during the render process OR using client side libraries to do similar things when we’re using dynamic rendering in HTML for instance. Keeping it simple and just generating embedded base64 or inline svg elements seems fine to me but. Realistically, being able to open up the drawio editor is a nice to have but not that much value in my case.

This discussion over on the asciidoctor repo seems particularly relevant — and to be honest this feature is probably better suited over there.

michaeljfazio avatar Apr 25 '21 11:04 michaeljfazio

@michaeljfazio is an integration based on the desktop app what you're looking for? That should be fairly straightforward to add.

pepijnve avatar Apr 26 '21 06:04 pepijnve

@michaeljfazio is an integration based on the desktop app what you're looking for? That should be fairly straightforward to add.

Not entirely sure I understand what you mean by "the Desktop App". I think you mean draw.io for desktop.

The integration, from the asciidoctor perspective, would probably be described better as an integration for the draw.io diagram file format (which is XML based). Does that answer your question?

michaeljfazio avatar Apr 26 '21 06:04 michaeljfazio

Yes the draw.io desktop app of course 😄 The original request here was to use the web service to do the rendering, but I was never able to figure out how to achieve that. I haven't looked at this in quite some time, so it might be possible now.

If installing the draw.io desktop application as a prerequisite is acceptable, then this integration should be straightforward to build.

pepijnve avatar Apr 26 '21 06:04 pepijnve

Note that I do consider the layer toggling functionality you suggested as out of scope. In general this extension integrates the functionality provided by the tools being integrated and doesn't try to add higher-level functionality. The draw.io CLI interface does not provide a means to toggle layers on and off. Doing so would probably require applying transformations to the XML (toggling visibility attribute values or something like that) before passing it to draw.io. I agree it would be powerful to add that, but I don't want to take on the maintenance burden of that kind of code. If you can get the draw.io developers to add a command line switch for layer toggling then I'm happy to add support for that option as well.

pepijnve avatar Apr 26 '21 06:04 pepijnve

Note that I do consider the layer toggling functionality you suggested as out of scope. In general this extension integrates the functionality provided by the tools being integrated and doesn't try to add higher-level functionality. The draw.io CLI interface does not provide a means to toggle layers on and off. Doing so would probably require applying transformations to the XML (toggling visibility attribute values or something like that) before passing it to draw.io. I agree it would be powerful to add that, but I don't want to take on the maintenance burden of that kind of code. If you can get the draw.io developers to add a command line switch for layer toggling then I'm happy to add support for that option as well.

Understood. Lots to unpack here.

Appreciate the maintenance burden that such functionality would likely add. I'm increasingly convinced that this might be implemented as an extension separate to asciidoctor-diagram. That said, i'll add some more context in lieu of a better place to put it right now.

Not sure that a dependency on the drawio desktop application is necessarily required. There are two ways to go about supporting drawio diagrams in a way that is commensurate with other projects that have done similar things. I'm not an expert on the drawio project, but i'll try to sum up what I believe are the options as best as I can.

Integration via API / Embedded Mode

This is how many solutions seem to work. Essentially, app.drawings.net exposes a configuration API. Many website and applications call this API, which defines a means of specifying the "drawio" base64 encoded diagram as well as various control options. The api accepts an "action" of type "export", for converting what is sent to the service back as the requested format (e.g. PNG, SVG, etc). There are of course many other options when using this API but this is the most relevant to this discussion.

There is also a headless docker container that implements the drawio protocol that people can run in self-hosted or local situations.

Relevant information:

Native Handling

I say "native" to indicate asciidoctor- would actually understand that drawio file format, which is implemented by mxGraph and is an XML description of the diagrams geometries and other visual elements. If I recall, the original version of this actually embedded the HTML compatible SVG element into the diagram, but this doesn't seem to be the case anymore? I could be mistaken, or it could just be when the diagram is exported as editable SVGs. In any case, my original thought was to just read that file (lets say it is an editable SVG), and directly encode the SVG element into the resulting HTML document. In terms of toggling layers, that would be a matter of changing the visibility properties of SVG groups on the fly like you say.

I believe the current iteration of drawio implements the underlying mxGraph format in Java. The code for understanding the format and rendering diagrams is part of the desktop version of drawio as you say.

It was once the case that you could use the jgraph library to read mxgraph (*.drawio) files and render SVGs. However, they seem to have archived that source repository. The npm stats however indicate that the library is very much active and being downloaded a lot. Which would suggest that it still implements mxGraph perfectly fine and can read and render the current mxGraph specification.

There appears to be java, javascript and dotnet implementations of the code in that repository. Nothing implemented directly in Ruby. But, if someone wanted to integrate the render functionality directly into an extension they could possibly use execjs.

Conclusion

  • The drawio format is called mxGraph.
  • The current drawio "engine" is implemented in java, and is invoked via API calls, sending the raw diagram data to be rendered or otherwise processed.
  • There are two primary paths forward to "integration" in an asciidoctor extension (via API calls, or natively understanding and rendering to SVG or other image format).

Lot's of ideas above. Happy to end the discussion there and see if the community can band together to sort out a way forward 👍

michaeljfazio avatar Apr 26 '21 07:04 michaeljfazio

There is a Visual Studio Code extension that allows to edit the diagrams locally, directly on your laptop, in Linux, Mac and Windows. In the assets/images folder of our documentation components, create your diagrams using the *.drawio.svg extension. These are automatically associated by Visual Studio Code with the extension, and provides a live editor with all the bells and whistles you might expect.

And then, well, just image::diagram.drawio.svg[] in your documents, git commit and push.

cforce avatar Jan 14 '22 09:01 cforce