Stackedit: Feature Request : Plantuml as UML Diagram provider

Created on 8 Oct 2014  Â·  11Comments  Â·  Source: benweet/stackedit

Hello

UML Diagrams are not very powerfull. It will be very cool to integrate Plantuml.

Plantuml manages all UML diagrams and it does well.

Plantuml Javascript library exists : http://plantuml.sourceforge.net/codejavascript.html

Best,

Guillaume

Most helpful comment

I can't find any "custom extensions" setting in the settings?

All 11 comments

I don't want to integrate PlantUML in StackEdit because it relies on a web service (it wouldn't work off-line).

That said, you can use this custom extension (to be copy/pasted in Settings>Extensions>UserCustom):

var r, c1, c2, c3, c4, previewContentsElt;
function encode64(data) {
    r = "";
    for (var i=0; i<data.length; i+=3) {
        if (i+2==data.length) {
            r +=append3bytes(data.charCodeAt(i), data.charCodeAt(i+1), 0);
        } else if (i+1==data.length) {
            r += append3bytes(data.charCodeAt(i), 0, 0);
        } else {
            r += append3bytes(data.charCodeAt(i), data.charCodeAt(i+1), data.charCodeAt(i+2));
        }
    }
    return r;
}

function append3bytes(b1, b2, b3) {
    c1 = b1 >> 2;
    c2 = ((b1 & 0x3) << 4) | (b2 >> 4);
    c3 = ((b2 & 0xF) << 2) | (b3 >> 6);
    c4 = b3 & 0x3F;
    r = "";
    r += encode6bit(c1 & 0x3F);
    r += encode6bit(c2 & 0x3F);
    r += encode6bit(c3 & 0x3F);
    r += encode6bit(c4 & 0x3F);
    return r;
}

function encode6bit(b) {
    if (b < 10) {
        return String.fromCharCode(48 + b);
    }
    b -= 10;
    if (b < 26) {
        return String.fromCharCode(65 + b);
    }
    b -= 26;
    if (b < 26) {
        return String.fromCharCode(97 + b);
    }
    b -= 26;
    if (b == 0) {
        return '-';
    }
    if (b == 1) {
        return '_';
    }
    return '?';
}

function makeUml() {
    window.RawDeflate && _.each(previewContentsElt.querySelectorAll('.prettyprint > .language-uml'), function(elt) {
        try {
            var preElt = elt.parentNode;
            var imgElt = $('<img>').attr({
                src: 'http://www.plantuml.com/plantuml/img/' + encode64(window.RawDeflate.deflate(elt.textContent))
            });
            preElt.parentNode.replaceChild(imgElt[0], preElt);
        }
        catch(e) {
        }
    });
}

userCustom.onPagedownConfigure = function(editor) {
    editor.hooks.chain("onPreviewRefresh", makeUml);
};

userCustom.onReady = function() {
    previewContentsElt = document.getElementById('preview-contents');
    $.getScript('//cdn.rawgit.com/dankogai/js-deflate/master/rawdeflate.js', makeUml);
};

It will turn

``````

Bob->Alice : foo
Bob<--Alice : foo

``````

into

If someone is trying to use PlantUML as uml provider in their local installation of StackEdit and don't care about the fact that is a web service the you can:

  1. Replace the file public/res/extensions/umlDiagrams.js with the one below.
  2. Execute the following commands
bower install pako --save
gulp bower-requirejs
gulp
node server.js

StackEdit PlantUML extension:

define([
    'jquery',
    'underscore',
    'utils',
    'logger',
    'pako',
    'classes/Extension'
], function($, _, utils, logger, pako, Extension) {

    /* PlantUML web service endpoint.
     * See http://plantuml.sourceforge.net/server.html
     */
    var plantumlServer = 'http://www.plantuml.com:80/plantuml/img/';

    /* PlantUML encoded input is very weird
     * This is just a pseudo copy paste of the reference Javascript
     * implementation available at:
     *
     *     http://plantuml.sourceforge.net/codejavascript2.html
     *
     * Expect instead of the rawdeflate library, pako was used so it can be
     * included as a requirejs dependency:
     *
     *     https://github.com/nodeca/pako
     */
    function encode64(data) {
        var r, i;
        r = '';
        for (i = 0; i < data.length; i += 3) {
            if (i + 2 == data.length) {
                r += append3bytes(data.charCodeAt(i), data.charCodeAt(i + 1), 0);
            } else if (i + 1 == data.length) {
                r += append3bytes(data.charCodeAt(i), 0, 0);
            } else {
                r += append3bytes(data.charCodeAt(i), data.charCodeAt(i + 1), data.charCodeAt(i + 2));
            }
        }
        return r;
    }

    function append3bytes(b1, b2, b3) {
        var r, c1, c2, c3, c4;
        c1 = b1 >> 2;
        c2 = ((b1 & 0x3) << 4) | (b2 >> 4);
        c3 = ((b2 & 0xF) << 2) | (b3 >> 6);
        c4 = b3 & 0x3F;
        r = '';
        r += encode6bit(c1 & 0x3F);
        r += encode6bit(c2 & 0x3F);
        r += encode6bit(c3 & 0x3F);
        r += encode6bit(c4 & 0x3F);
        return r;
    }

    function encode6bit(b) {
        if (b < 10) {
            return String.fromCharCode(48 + b);
        }
        b -= 10;
        if (b < 26) {
            return String.fromCharCode(65 + b);
        }
        b -= 26;
        if (b < 26) {
            return String.fromCharCode(97 + b);
        }
        b -= 26;
        if (b === 0) {
            return '-';
        }
        if (b === 1) {
            return '_';
        }
        return '?';
    }

    function plantumlConvert(text) {
        var converted = encode64(pako.deflate(text, { to: 'string' }));
        return converted;
    }

    /*
     * StackEdit extension implementation
     */

    var umlDiagrams = new Extension('umlDiagrams', 'UML Diagrams', true);

    umlDiagrams.onPagedownConfigure = function(editor) {

        var previewContentsElt = document.getElementById('preview-contents');

        editor.hooks.chain('onPreviewRefresh', function() {

            _.each(previewContentsElt.querySelectorAll('.prettyprint > .language-uml'), function(elt) {
                try {
                    var preElt = elt.parentNode;
                    var imgElt = $('<img>').attr({
                        src: plantumlServer + plantumlConvert(elt.textContent)
                    });
                    preElt.parentNode.replaceChild(imgElt[0], preElt);
                }
                catch(e) {
                    console.error(e);
                }
            });

        });
    };

    return umlDiagrams;
});

Regards

The provided user extension works great as long as you do not use any UTF-8 char in the uml. For example,

alice -> bob : foö
bob -> alice: bar

produces:

clipboard01

and the following does not produce an image, but an error:

alice -> böb : foo
böb -> alice: bar

The problema can be fixed by changing encode64(window.RawDeflate.deflate(elt.textContent)) by encode64(window.RawDeflate.deflate(unescape(encodeURIComponent(elt.textContent)))) in the code provided by benweet.

Also in favor of having support for PlantUML, albeit with a webservice. Most users will not be using stackedit off-line anyway.

PlantUML is available as a JAR and can also be run on the server on which stackedit runs instead of calling the publicly available web service.

There are many optional features, that would be one more.... AND: the "sequence" is buggy or at least incomplete.

What is exactly wrong with the sequence diagrams? In my experience the support for PlantUML is very good. So filing a bug report should help solve it.

PlantUML is working fine.

I'm talking about the ```sequence interpreter.
the js-sequence says it supports participant's aliases, but I couldn't get
even the "participant" to work:

snapshot
​
As you can see, I've created some participants, and it rendered them. But
when I tried to link them, it created NEW boxes, instead of the ones that
already were there.
I thought it was a "special chars ('ó') issue, but changind it to "TDocs"
didn't work either.

Also, since the js-sequence seems limited, I moved to plantUML/graphviz: it
has the most common UML diagrams, it's syntax is "consistent", and I
already have some diagram made with it :D that I can now properly document.
And it's far more customizable.

And, the "offline" issue is not really an issue: I can compose the document
offline, and the diagram later... and export even later...

2016-04-15 11:01 GMT-03:00 Pander [email protected]:

What is exactly wrong with the sequence diagrams? In my experience the
support for PlantUML is very good. So filing a bug report should help solve
it.

—
You are receiving this because you commented.
Reply to this email directly or view it on GitHub
https://github.com/benweet/stackedit/issues/569#issuecomment-210474520

Atte.,

_Manuel López_

Ah, good to hear. I can help out with overriding colors and fonts for PlantUML if you need.

We're preparing a "default" skinparam file for PlantUML, but for
documentation purposes, I will propose to use a simple and effective:

skinparam monochrome true

and go with it: I'e tested with two diagrams and it looks good enough. :)
As I said, plantUML/graphViz is the best diagrammer I've found. Versatile.

I hope it makes through the StackEdit's mainstream (just to keep the
conversation on-topic! :D).

I can't find any "custom extensions" setting in the settings?

Was this page helpful?
0 / 5 - 0 ratings