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

Auto-wrap, inline config, initialization, dark theme tweaks, etc #1458

Merged
merged 8 commits into from
Jun 14, 2020
Merged

Auto-wrap, inline config, initialization, dark theme tweaks, etc #1458

merged 8 commits into from
Jun 14, 2020

Conversation

chrismoran-bkt
Copy link
Contributor

@chrismoran-bkt chrismoran-bkt commented Jun 8, 2020

📑 Summary

Added an auto-wrap option for (non 2.x svg text) sequence diagram notes, messages, actor descriptions, etc.
Added the capability to parse in inline initialize json as well as a config json
More than a couple tweaks and fixes.

Special thanks to Carys Mills @ https://medium.com/@CarysMills/wrapping-svg-text-without-svg-2-ecbfb58f7ba4 for the basis fro the wrapLabels and breakWords logic.

I have not added all of the unit-tests necessary for me to feel comfortable with this PR yet. I wanted to get eyeballs on this earlier rather than later. Once I finish up the unit tests on my local I'll change this to a formal PR.

📏 Design Decisions

I wanted auto-wrapping in svg text so my sequence diagrams looked like this:

image

and not like this:

image

I updated the parser logic to properly support automatic wrapping of notes, messages, and actor descriptions. The margins are respected.

Enabling autowrapping requires nothing more than this:

sequenceDiagram
  %%wrap
  participant a as aa
  participant b as bb
  participant c as cc

  a->>+b: Hello
  b->>-a: World
  a->>+c: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur at felis vel justo semper rhoncus. Morbi in ipsum facilisis, dictum lorem luctus, accumsan ligula. Etiam et auctor nisi, ac cursus mauris. Ut finibus nunc ante, vitae tempus magna pharetra eu.

Incidentally, initialization ala mermaid.initialize(...) is now available within the text block as well:

%%initialize: { 'logLevel': 0, 'theme': 'dark' }
sequenceDiagram
  %%config: { 'fontFamily':'.SF NS','fontSize':14,'fontWeight':400 }
  %%wrap
  participant a as aa
  participant b as bb
  participant c as cc

  a->>+b: Hello
  b->>-a: World
  a->>+c: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur at felis vel justo semper rhoncus. Morbi in ipsum facilisis, dictum lorem luctus, accumsan ligula. Etiam et auctor nisi, ac cursus mauris. Ut finibus nunc ante, vitae tempus magna pharetra eu.

It doesn't matter what quotes you use, I change them to "" to make the json proper anyway. The only requirement is: you need to make the json well-formed or you'll have very little showing up on the page. (Read: JSON parsing errors). Also, you can use %%initialize or %%init. Also, %%config, %%conf, %%configuration, and %%configure all work equally too.

Location kinda matters for the %%initialize statement; just like sequenceDiagram. The init statement must be first (if it exists at all). wrap can be anywhere as it is more of a directive than a statement. Once it is found, all of the relevant texts will be wrapped where necessary.

EDIT: I’ve changed init, initialize, conf, config, configure, configuration, and wrap to be effectively directives. As far as I could tell, directives didn’t exist in the grammar but seem to be parser-friendly as well as backwards-compatible. This is a plus in my opinion.

Added inline config and init(ialization) grammar
Added reinitialize functionality to mermaidAPI (not to be confused with initialize)
Added actorFontWeight, noteFontWeight, messageFontWeight, wrapEnabled, wrapPadding
Added wrapLabel and breakWord functions to intelligently wrap text based on a pixel-based width instead of column-based
  - The implementation is largely from Carys Mills: https://medium.com/@CarysMills/wrapping-svg-text-without-svg-2-ecbfb58f7ba4
  - Made slight modifications for mermaid-js
Fixed dark theme color inconsistencies for sequence diagrams
Removed !important from sequence scss as this prevents any client overrides
Fixed various invalid css values in sequence scss which prevented proper rendering of various elements
Added detectInit to utils for initialization json detection
Updated detectType to support the existence or absence of the intialization configuration
Updated calculateTextWidth to include fontWeight
Copy link
Collaborator

@knsv knsv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff!

It has been wish for a while to have the possibility change some configuration via directives in the diagram as per some of the changes in this PR. So this is great!

Some things to keep in mind:

  • As we want the directives eventually to be available for all diagrams it is important that the syntax fits (and I think the comment is a goos start, perhaps we could add something more like %%{ xyz ...}. That could simplify parsing, %%{ => lexer goes into directive state, limiting the risk of syntax clashes with the rest of the diragram.
  • Backwards compatability. It is important the the existing wrapping methods continue to work as before when there are no directives in play. We don't want to break diagrams authored by end users.
  • Cypress rendering tests is a great way of making sure this functionalty continues to be verified in future releases.

For more info about the lexer state/stack, look here https://gerhobbelt.github.io/jison/docs/ (search for pushState).

Again, good start! Looking forward to the full PR

Implemented directives per PR review comment:

%%{directive: json-encoded-arg-string}%%

example:

%%{init: { 'logLevel': 0, 'theme': 'dark' }}%%

Also changed wrap and config to directives:

%%{wrap}%%
%%{config: { 'fontSize': 18 }}%%
@chrismoran-bkt
Copy link
Contributor Author

chrismoran-bkt commented Jun 11, 2020

Good stuff!

It has been wish for a while to have the possibility change some configuration via directives in the diagram as per some of the changes in this PR. So this is great!

Some things to keep in mind:

  • As we want the directives eventually to be available for all diagrams it is important that the syntax fits (and I think the comment is a goos start, perhaps we could add something more like %%{ xyz ...}. That could simplify parsing, %%{ => lexer goes into directive state, limiting the risk of syntax clashes with the rest of the diragram.
  • Backwards compatability. It is important the the existing wrapping methods continue to work as before when there are no directives in play. We don't want to break diagrams authored by end users.
  • Cypress rendering tests is a great way of making sure this functionalty continues to be verified in future releases.

For more info about the lexer state/stack, look here https://gerhobbelt.github.io/jison/docs/ (search for pushState).

Again, good start! Looking forward to the full PR

I've implemented the directive support as you've described: %%{directive[: json-encoded-arg-string]}%%

Example diagram(s) with my changes:

%%{init: { 'theme': 'dark' } }%%
sequenceDiagram
%%{wrap}%%
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
Note left of Alice: Bob thinks
Bob->>Alice: Fine!

Produces: (Roughly - because the browser I use has some custom CSS)

image

A contrived example of overriding the %%{wrap}%% directive:

%%{init:{'theme':'dark'}}%%
sequenceDiagram
%%{wrap}%%
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
Bob-->Alice:nowrap: Ok. I appreciate you contacting me.
Note left of Alice: Bob thinks
Bob->>Alice: Fine!

Note the use of :nowrap: in the Bob-->Alice line. This means that line will grow and expand the width of the diagram indefinitely. The first line: Alice->>Bob: is wrap by default (due to the directive). And so it will wrap until, of course, the width between actors is enough for the text to sit on a single line.

image

The normal rules of precedence take effect with the wrap directive vs the inline wrap | nowrap:

inline > directive > default (no wrapping)

No wrapping is the default, assuming no inline wrap statement and no directive present. Next is the %%{wrap}%% directive. Finally, the highest precedence goes to the line-level statement.

I've made a few changes/tweaks to the rendering of note boxes (mostly because wrapping has caused height differences of course). These changes should not affect any current tests (as all current tests assume no wrapping - thank goodness)

Will you require a 'wrap' test for every current nowrap test? If so, this will take a while :)

 - JavaFX does not support lookbehind
 - (?) It also appears that named regex groups are also unsupported for both mermaid and javafx

Update:
 - Fixed an issue where setLogLevel did not properly handle 'named' log levels
 - Backwards compatibility should be preserved, any/all %%{...}%% directives will be correctly processed by the grammar and properly ignored for any/all graph types that do not support them.

 - Multiline directives will render an error (as they should) if they are not accounted for in the .jison grammar
@chrismoran-bkt chrismoran-bkt marked this pull request as ready for review June 14, 2020 15:48
@chrismoran-bkt
Copy link
Contributor Author

I've cleaned up the code about as much as I can. Here is a quick rundown of the features:

Directives

Init directives

With this version, directives are supported. Technically there are two flavors of directive: init/initialize and everything else. The init/initialize directive is parsed early in the flow enough to be able to re-initialize mermaid with a new configuration object. Example:

%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
graph >
A-->B

will set the logLevel to debug and the theme to dark for a flowchart diagram.

Note: init or initialize are both acceptable as init directives. Also note that init directives are coalesced. This means:

%%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%%
%%{initialize: { 'logLevel': 'fatal', "theme":'dark', 'startOnLoad': true } }%%
...

will result an init object looking like this:

{
  logLevel: 'fatal',
  theme: 'dark',
  startOnLoad: true
}

to be sent to mermaid.initialize(...)

Other directives

The other flavor of directive is everything else. In this category are any directives that follow the graph type declaration. Essentially, these directives will not be processed early in the flow like the init directive. Each individual graph type will handle these directives. As an example:

%%{init: { 'logLevel': 'debug', 'theme': 'dark' } }%%
sequenceDiagram
%%{config: { 'fontFamily': 'Menlo', 'fontSize': 18, 'fontWeight': 400} }%%
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice

This will set the logLevel to debug and theme to dark for a sequence diagram. Then, during processing, the config for the sequence diagram is set by the config directive. This directive is handled in the sequenceDb.js. In this example, the fontFamily, fontSize, and fontWeight are all set for this sequence diagram.

Backwards Compatibility

Init directives and any other non-multiline directives should be backwards compatible because they will be treated as comments in prior versions of mermaid-js.

Multiline directives, however, will pose an issue and will render an error. This is unavoidable.

Wrapping

The %%{wrap}%% directive and the inline wrap: text hint have also been added for sequence diagrams. This has been explained in my previous comments and has not materially changed.

@knsv
Copy link
Collaborator

knsv commented Jun 14, 2020

This looks like a thorough job. Very positive with updated docs as well. Without that no one will know how to use this feature. Also good with some attention to the dark theme. I think many people use it.

I have an idea of making rendering tests with showcases of each diagram type with each theme to get better focus on the themes.

@knsv
Copy link
Collaborator

knsv commented Jun 14, 2020

The issue with compatability multi line directives only offers a problem if you use a diagram written for a newer version of mermaid with an older version.

@knsv knsv merged commit 145d337 into mermaid-js:develop Jun 14, 2020
@knsv
Copy link
Collaborator

knsv commented Jun 14, 2020

Merged, but the rendering tests failed somewhat. It is the not text for non dark theme. Maybe the update for the dark theme affected it somehow.
image

@chrismoran-bkt
Copy link
Contributor Author

chrismoran-bkt commented Jun 14, 2020 via email

@knsv
Copy link
Collaborator

knsv commented Jun 14, 2020

I also added the nice directives comment you wrote above as a separate directives section in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants