Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated SVG works poorly outside web browsers #58

Closed
bjowes opened this issue Dec 14, 2014 · 13 comments
Closed

Generated SVG works poorly outside web browsers #58

bjowes opened this issue Dec 14, 2014 · 13 comments
Assignees
Labels
Status: Approved Is ready to be worked on Type: Enhancement New feature or request

Comments

@bjowes
Copy link
Contributor

bjowes commented Dec 14, 2014

The generated SVG contains text encapsulated inside foreignObject elements. Inside the foreignObjects, there are divs to handle text with linebreaks. However, divs doesn't display in other SVG viewers than web browsers.
A related issue is the <br> tags for linebreaks. Those are invalid in XML. They could be replaced by <br/> to allow the SVG to be opened outside web browsers, but the text will still not be rendered.

@knsv
Copy link
Collaborator

knsv commented Dec 14, 2014

Instead of html labels we should try to use text elements with tspan elements inside for this. For instance, the generated code with html labels are:

<foreignObject width="104" height="72">
   <div style="display: inline-block; white-space: nowrap;">Really<br>
      long text <br>
      with linebreak<br>
      in an Odd shape
   </div>
</foreignObject>

Instead the text should be represented by something like this:

<text text-anchor="start" x="1" y="1">
    <tspan dy="1em" x="0">Really</tspan>
    <tspan dy="1em" x="0">long text</tspan>
    <tspan dy="1em" x="0">with linebreak</tspan>
    <tspan dy="1em" x="0">in an Odd shape</tspan>
</text>

@bjowes
Copy link
Contributor Author

bjowes commented Dec 14, 2014

Yes, that seems to be the standard way in SVG. Will look into this when I am finished with the issue #24.

@wonderwhy-er
Copy link

foreignObject apperantly also breaks functionality of converting SVG -> Canvas -> PNG image
Was trying to add functionality of 'save as image' in browser but failed so far

@timelyportfolio
Copy link

As another hopefully helpful reference, here is how d3plus handles the text wrapping http://d3plus.org/examples/utilities/a39f0c3fc52804ee859a/.

Thanks so much @knsv for such fine work. We are making it into an htmlwidget to make it easily available to R users.

@bjowes
Copy link
Contributor Author

bjowes commented Jan 11, 2015

Thanks @timelyportfolio, that looks cool!
With the current model for text in mermaid, the user does not need to care about the width of individual nodes - instead they specify the linebreaks manually. It is a tempting alternative to be able to set a specific node width instead, and use something like d3plus to reformat the text to fit inside the node.

However, mermaid builds on dagre-d3 to generate the SVG content, including the text labels. It would be more natural to incorporate this kind of text wrapping support into dagre-d3 instead.

The work I have in progress on the labels is to support both label variants of dagre-d3 - HTML version and SVG version. If dagre-d3 is improved, we can then make use of that directly in mermaid.

@knsv
Copy link
Collaborator

knsv commented Jan 25, 2015

This has been included in release 0.3.3

@knsv knsv closed this as completed Jan 25, 2015
@wonderwhy-er
Copy link

@knsv cool!
Wanted to check how it works now and integrate in to tool I am building on top of mermaid.
But is full browser 0.3.3 version available somewhere for download already?

@knsv
Copy link
Collaborator

knsv commented Jan 27, 2015

It is avaiable using npm/bower or from download (cdn) rihght now. If you are making a tool with user input you might want to take a look at the errorHandling/syntax check api in 0.3.3:

Error handling

When the parser encounters invalid syntax the mermaid.parseError function is called. It is possible to override this function in order to handle the error in an application specific way.

Parsing text without rendering

It is also possible to validate the syntax before rendering in order to streamline the user experience. The function mermaid.parse(txt) takes a text string as an argument and returns true if the text is syntactically correct and false if it is not. The parseError function will be called when the parse function returns false.

The code-example below in meta code illustrates how this could work:

mermaid.parseError = function(err,hash){
    displayErrorInGui(err);
};

var textFieldUpdated = function(){
    var textStr = getTextFromFormField('code');

    if(mermaid.parse(textStr)){
        reRender(textStr)
    }
};

bindEventHandler('change', 'code', textFieldUpdated);

@wonderwhy-er
Copy link

Played with 0.3.3
Firstly it seems syntax changed.
';' is not needed anymore and its more strict with spaces and may be other symbols.

Secondly lines reported in parseError are weird. Like in

graph LR
    A[Square Rect] -- Link text --> B((Circle))
    A --> C(Round Rect)
    B --> D{Rhombus}
    C --> D 

It reports:

Parse error on line 9:
...ombus}
    C --&gt; D 
----------------------^
Expecting 'SEMI', 'EOF', 'NEWLINE', '--', '-.', '==', 'ARROW_POINT', 'ARROW_CIRCLE', 'ARROW_CROSS', 'ARROW_OPEN', 'DOTTED_ARROW_POINT', 'DOTTED_ARROW_CIRCLE', 'DOTTED_ARROW_CROSS', 'DOTTED_ARROW_OPEN', 'THICK_ARROW_POINT', 'THICK_ARROW_CIRCLE', 'THICK_ARROW_CROSS', 'THICK_ARROW_OPEN', got 'SPACE'

So error on line 9 in file of 5 lines.

@knsv
Copy link
Collaborator

knsv commented Jan 28, 2015

Hello!

Are you sure that the actual character are not in fact > that is an escaped code for > and renders to > in the browser? When I copy the text from your email to my test page which is using 0.3.3 it renders fine so the syntax is ok.

I hope this gives you some help.

Knut Sveidqvist
Sent with Sparrow (http://www.sparrowmailapp.com/?sig)

On Wednesday 28 January 2015 at 21:40, wonderwhy-er wrote:

Played with 0.3.3
Firstly it seems syntax changed.
';' is not needed anymore and its more strict with spaces and may be other symbols.
Secondly lines reported in parseError are weird. Like in
graph LR A[Square Rect] -- Link text --> B((Circle)) A --> C(Round Rect) B --> D{Rhombus} C --> D
It reports:
Parse error on line 9: ...ombus} C --> D ----------------------^ Expecting 'SEMI', 'EOF', 'NEWLINE', '--', '-.', '==', 'ARROW_POINT', 'ARROW_CIRCLE', 'ARROW_CROSS', 'ARROW_OPEN', 'DOTTED_ARROW_POINT', 'DOTTED_ARROW_CIRCLE', 'DOTTED_ARROW_CROSS', 'DOTTED_ARROW_OPEN', 'THICK_ARROW_POINT', 'THICK_ARROW_CIRCLE', 'THICK_ARROW_CROSS', 'THICK_ARROW_OPEN', got 'SPACE'
So error on line 9 in file of 5 lines.


Reply to this email directly or view it on GitHub (#58 (comment)).

@JozoVilcek
Copy link

Is this issue resolved? With v0.3.3 I observe foreignObject(s) in generated graphs, but not sequence diagrams. Graph layouts seems to be sensitive to css fonts a line heights settings. Some replacements of foreign objects is still going on here.

@bjowes
Copy link
Contributor Author

bjowes commented Feb 9, 2015

For the flowChart graph type, a configuration setting is required to generate SVGs without foreignObject. Set htmlLabels to false in the mermaid config to enable that. Granted this need to get into the wiki.
The reason that htmlLabels are still enabled by default, is that the pure SVG labels provided by dagre-d3 are limited in styling. The plan was to improve the labels in dagre-d3 to mimic the style of the current html Labels, and then make text labels default. But as long as you can accept the slightly different style, you can use them already.

@JozoVilcek
Copy link

I will try out the configuration setting. Thanks a lot for clarification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Approved Is ready to be worked on Type: Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants