diff --git a/_posts/2021/05/2021-05-21-diagrams-from-textual-descriptions.md b/_posts/2021/05/2021-05-21-diagrams-from-textual-descriptions.md new file mode 100644 index 0000000000000000000000000000000000000000..4f74b8f70d442a7309c487cc67afce80bb728b83 --- /dev/null +++ b/_posts/2021/05/2021-05-21-diagrams-from-textual-descriptions.md @@ -0,0 +1,480 @@ +--- +title: "GitLab - Create Diagrams From Textual Descriptions" +title_image: clark-tibbs-oqStl2L5oxI-unsplash.jpg +data: 2021-05-21 +authors: + - huste +layout: blogpost +categories: + - tutorials +excerpt: > + Recently, the Helmholtz-wide software development platform has been extended + with the ability to create diagrams from textual descriptions. + This post will help you getting started with this new feature. + +--- + +{{ page.excerpt }} + +## Quick-Start Example +Let us jump right in with an example by creating a UML sequence diagram. +Any of these examples can be used in a place on <https://gitlab.hzdr.de> +where Markdown is supported: + * Comments + * Issues + * Merge requests + * Milestones + * Snippets (the snippet must be named with a `.md` extension) + * Wiki pages + * Markdown documents inside repositories + +Therefore, put this content describing the diagram in any of the items +listed above. + + ```plantuml + @startuml + participant User + + User -> A: DoWork + activate A + + A -> B: << createRequest >> + activate B + + B -> C: DoWork + activate C + C --> B: WorkDone + destroy C + + B --> A: RequestCreated + deactivate B + + A -> User: Done + deactivate A + @enduml + ``` + +This description is then converted into this sequence diagram. + + + +## How Does That Work? +In the background a tool called [Kroki](https://kroki.io) is doing the magic. +It takes the textual description and converts it into an image. +The example shown above is using [PlantUML](https://plantuml.com/) to create +the diagram of our choice (see line 1). + +So all you need to do is to create the textual description of your diagram and +put it into GitLab Markdown. +When viewing the content, in the background we will make sure that you are +presented an image of your diagram description. + +## Step-By-Step Guide +In this example our goal is to create a visual representation of JSON data. +Let's take this example JSON data. + +<details> + <summary>Show JSON data</summary> + <div markdown=1> +```json +{ + "firstName": "John", + "lastName": "Smith", + "age": 28, + "address": { + "streetAddress": "Bautzner Landstr. 400", + "city": "Dresden", + "state": "Saxony", + "postalCode": "01328" + }, + "offices": [ + { + "building": 512, + "room": 1234 + }, + { + "building": 312, + "room": 3 + } + ], + "departments": [] +} +``` + </div> +</details> + +We will use PlantUML to [display the JSON data](https://plantuml.com/json). + +At first, we need to tell GitLab that we want to create a diagram using +PlantUML. +This is why we create a Markdown code block using PlantUML for syntax highlighting. + + ```plantuml + + ``` + +The [PlantUML documentation](https://plantuml.com/json) tells us how such a +visual representation can be created. +In this case you need to embed the JSON data into a block starting with +`@startjson` and ending with `@endjson`. + + ```plantuml + @startjson + { + "firstName": "John", + "lastName": "Smith", + "age": 28, + "address": { + "streetAddress": "Bautzner Landstr. 400", + "city": "Dresden", + "state": "Saxony", + "postalCode": "01328" + }, + "offices": [ + { + "building": 512, + "room": 1234 + }, + { + "building": 312, + "room": 3 + } + ], + "departments": [] + } + @endjson + ``` + +You will be presented an image as shown below. + + + +## What Else Can Be Done? +The new feature is not limited to using PlantUML. +The new integration gives you access to more than that. +It supports, among others, [Vega](https://github.com/vega/vega), +[C4 with PlantUML](https://github.com/RicardoNiepel/C4-PlantUML), +[GraphViz](https://www.graphviz.org/) or +[BlockDiag](https://github.com/blockdiag/blockdiag). +For a complete list please refer to the official +[list of supported diagram types and formats](https://kroki.io/#support). + +### Vega + +<details> + <summary>Show code</summary> + <div markdown="1"> + ```vega + { + "$schema": "https://vega.github.io/schema/vega/v5.json", + "description": "A nested bar chart example, with bars grouped by category.", + "width": 300, + "padding": 5, + "autosize": "pad", + + "signals": [ + { + "name": "rangeStep", "value": 20, + "bind": {"input": "range", "min": 5, "max": 50, "step": 1} + }, + { + "name": "innerPadding", "value": 0.1, + "bind": {"input": "range", "min": 0, "max": 0.7, "step": 0.01} + }, + { + "name": "outerPadding", "value": 0.2, + "bind": {"input": "range", "min": 0, "max": 0.4, "step": 0.01} + }, + { + "name": "height", + "update": "trellisExtent[1]" + } + ], + + "data": [ + { + "name": "tuples", + "values": [ + {"a": 0, "b": "a", "c": 6.3}, + {"a": 0, "b": "a", "c": 4.2}, + {"a": 0, "b": "b", "c": 6.8}, + {"a": 0, "b": "c", "c": 5.1}, + {"a": 1, "b": "b", "c": 4.4}, + {"a": 2, "b": "b", "c": 3.5}, + {"a": 2, "b": "c", "c": 6.2} + ], + "transform": [ + { + "type": "aggregate", + "groupby": ["a", "b"], + "fields": ["c"], + "ops": ["average"], + "as": ["c"] + } + ] + }, + { + "name": "trellis", + "source": "tuples", + "transform": [ + { + "type": "aggregate", + "groupby": ["a"] + }, + { + "type": "formula", "as": "span", + "expr": "rangeStep * bandspace(datum.count, innerPadding, outerPadding)" + }, + { + "type": "stack", + "field": "span" + }, + { + "type": "extent", + "field": "y1", + "signal": "trellisExtent" + } + ] + } + ], + + "scales": [ + { + "name": "xscale", + "domain": {"data": "tuples", "field": "c"}, + "nice": true, + "zero": true, + "round": true, + "range": "width" + }, + { + "name": "color", + "type": "ordinal", + "range": "category", + "domain": {"data": "trellis", "field": "a"} + } + ], + + "axes": [ + { "orient": "bottom", "scale": "xscale", "domain": true } + ], + + "marks": [ + { + "type": "group", + + "from": { + "data": "trellis", + "facet": { + "name": "faceted_tuples", + "data": "tuples", + "groupby": "a" + } + }, + + "encode": { + "enter": { + "x": {"value": 0}, + "width": {"signal": "width"} + }, + "update": { + "y": {"field": "y0"}, + "y2": {"field": "y1"} + } + }, + + "scales": [ + { + "name": "yscale", + "type": "band", + "paddingInner": {"signal": "innerPadding"}, + "paddingOuter": {"signal": "outerPadding"}, + "round": true, + "domain": {"data": "faceted_tuples", "field": "b"}, + "range": {"step": {"signal": "rangeStep"}} + } + ], + + "axes": [ + { "orient": "left", "scale": "yscale", + "ticks": false, "domain": false, "labelPadding": 4 } + ], + + "marks": [ + { + "type": "rect", + "from": {"data": "faceted_tuples"}, + "encode": { + "enter": { + "x": {"value": 0}, + "x2": {"scale": "xscale", "field": "c"}, + "fill": {"scale": "color", "field": "a"}, + "strokeWidth": {"value": 2} + }, + "update": { + "y": {"scale": "yscale", "field": "b"}, + "height": {"scale": "yscale", "band": 1}, + "stroke": {"value": null}, + "zindex": {"value": 0} + }, + "hover": { + "stroke": {"value": "firebrick"}, + "zindex": {"value": 1} + } + } + } + ] + } + ] + } + ``` + </div> +</details> + + + +Taken from <https://vega.github.io/vega/examples/nested-bar-chart/>. + +### C4 with PlantUML + +<details> + <summary>Show code</summary> + <div markdown="1"> + ```plantuml + @startuml "techtribesjs" + !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml + ' uncomment the following line and comment the first to use locally + ' !include C4_Container.puml + + LAYOUT_TOP_DOWN() + 'LAYOUT_AS_SKETCH() + LAYOUT_WITH_LEGEND() + + + Person_Ext(anonymous_user, "Anonymous User") + Person(aggregated_user, "Aggregated User") + Person(administration_user, "Administration User") + + System_Boundary(c1, "techtribes.js"){ + + Container(web_app, "Web Application", "Java, Spring MVC, Tomcat 7.x", "Allows users to view people, tribes, content, events, jobs, etc. from the local tech, digital and IT sector") + + ContainerDb(rel_db, "Relational Database", "MySQL 5.5.x", "Stores people, tribes, tribe membership, talks, events, jobs, badges, GitHub repos, etc.") + + Container(filesystem, "File System", "FAT32", "Stores search indexes") + + ContainerDb(nosql, "NoSQL Data Store", "MongoDB 2.2.x", "Stores from RSS/Atom feeds (blog posts) and tweets") + + Container(updater, "Updater", "Java 7 Console App", "Updates profiles, tweets, GitHub repos and content on a scheduled basis") + } + + System_Ext(twitter, "Twitter") + System_Ext(github, "GitHub") + System_Ext(blogs, "Blogs") + + + Rel(anonymous_user, web_app, "Uses", "HTTPS") + Rel(aggregated_user, web_app, "Uses", "HTTPS") + Rel(administration_user, web_app, "Uses", "HTTPS") + + Rel(web_app, rel_db, "Reads from and writes to", "SQL/JDBC, port 3306") + Rel(web_app, filesystem, "Reads from") + Rel(web_app, nosql, "Reads from", "MongoDB wire protocol, port 27017") + + Rel_U(updater, rel_db, "Reads from and writes data to", "SQL/JDBC, port 3306") + Rel_U(updater, filesystem, "Writes to") + Rel_U(updater, nosql, "Reads from and writes to", "MongoDB wire protocol, port 27017") + + Rel(updater, twitter, "Gets profile information and tweets from", "HTTPS") + Rel(updater, github, "Gets information about public code repositories from", "HTTPS") + Rel(updater, blogs, "Gets content using RSS and Atom feeds from", "HTTP") + + Lay_R(rel_db, filesystem) + + @enduml + ``` + </div> +</details> + + + +Taken from <https://github.com/plantuml-stdlib/C4-PlantUML>. + +### GraphViz + +<details> + <summary>Show code</summary> + <div markdown="1"> + {% raw %} + ```graphviz + digraph G { + concentrate=True; + rankdir=TB; + node [shape=record]; + 140087530674552 [label="title: InputLayer\n|{input:|output:}|{{[(?, ?)]}|{[(? , ?)]}}"]; + 140087537895856 [label="body: InputLayer\n|{input:|output:}|{{[(?, ?)]}|{[(?, ?)]}}"]; + 140087531105640 [label="embedding_2: Embedding\n|{input:|output:}|{{(?, ?)}|{ (?, ?, 64)}}"]; + 140087530711024 [label="embedding_3: Embedding\n|{input:|output:}|{{(?, ?)}|{ (?, ?, 64)}}"]; + 140087537980360 [label="lstm_2: LSTM\n|{input:|output:}|{{(?, ?, 64)}|{(?, 128)}}"]; + 140087531256464 [label="lstm_3: LSTM\n|{input:|output:}|{{(?, ?, 64)}|{(?, 32) }}"]; + 140087531106200 [label="tags: InputLayer\n|{input:|output:}|{{[(?, 12)]}|{[(? , 12)]}}"]; + 140087530348048 [label="concatenate_1: Concatenate\n|{input:|output:}|{{[(?, 128), (?, 32), (?, 12)]}|{(?, 172)}}"]; + 140087530347992 [label="priority: Dense\n|{input:|output:}|{{(?, 172)}|{(?, 1) }}"]; + 140087530711304 [label="department: Dense\n|{input:|output:}|{{(?, 172)}|{(?, 4)}}"]; + 140087530674552 -> 140087531105640; + 140087537895856 -> 140087530711024; + 140087531105640 -> 140087537980360; + 140087530711024 -> 140087531256464; + 140087537980360 -> 140087530348048; + 140087531256464 -> 140087530348048; + 140087531106200 -> 140087530348048; + 140087530348048 -> 140087530347992; + 140087530348048 -> 140087530711304; + } + ``` + {%endraw%} + </div> +</details> + + + +Taken from <https://graphviz.org/Gallery/directed/neural-network.html>. + +### BlockDiag + +<details> + <summary>Show code</summary> + <div markdown="1"> + ```blockdiag + blockdiag { + A -> B -> C -> D; + A -> E -> F -> G; + } + ``` + </div> +</details> + + + +Taken from <http://blockdiag.com/en/blockdiag/examples.html>. + +## Deployment +The service is provided by HIFIS Software and is hosted entirely on HZDR +servers. +It does not share any data with external providers. +As usual, the deployment can be reproduced via the corresponding +[project](https://gitlab.hzdr.de/hifis-software-deployment/kroki) - +only accessible for employees within Helmhholtz. + +## More Examples +More examples can be found in the +[GitLab example project](https://gitlab.hzdr.de/examples/kroki). + +## Comments and Suggestions + +If you have suggestions, questions, or queries, please don't hesitate to write us. + +<a href="{% link contact.md %}" + class="btn btn-outline-secondary" + title="HIFIS Helpdesk"> + Contact us! <i class="fas fa-envelope"></i></a>