Types for PlantUML Parser


plantuml-parser 0.0.12 introduces TypeScript declarations. Now you can parse PlantUML and get a fully typed result. PlantUML diagrams are awesome! In this post I first give a brief introduction into PlantUML. Then I will show how you can use plantuml-parser with TypeScript to make the most out of your diagrams.

Bob leaves Alice She wouldn’t be my type either

Show source
@startuml
actor Alice
actor Bob

Alice -> Bob: Tells Bob that\n she does not like\ntypes
Bob --> Alice: Leaves her
@enduml
Show parser result
[
  {
    "elements": [
      {
        "left": "Alice",
        "right": "Bob",
        "leftType": "Unknown",
        "rightType": "Unknown",
        "leftArrowHead": "",
        "rightArrowHead": ">",
        "leftArrowBody": "-",
        "rightArrowBody": "-",
        "leftCardinality": "",
        "rightCardinality": "",
        "label": "Tells Bob that\\n she does not like\\ntypes",
        "hidden": false
      },
      {
        "left": "Bob",
        "right": "Alice",
        "leftType": "Unknown",
        "rightType": "Unknown",
        "leftArrowHead": "",
        "rightArrowHead": ">",
        "leftArrowBody": "-",
        "rightArrowBody": "-",
        "leftCardinality": "",
        "rightCardinality": "",
        "label": "Leaves her",
        "hidden": false
      }
    ]
  }
]

Table of Contents

Why you should use PlantUML

PlantUML is an open-source tool allowing users to create UML diagrams from a plain text language. The language of PlantUML is an example of a Domain-specific language. It uses Graphviz software to lay out its diagrams.

– Source: wikipedia/PlantUML

I use PlantUML daily. A textual description of design diagrams alongside the source code is my definition of a living document. You know the pain of out of date documentation. Did you ever ask yourself why this happens? As a software developer I do reject a tool if it does not make my life easier. Writing sound and solid source code is already hard enough. Having to deal with a ton of different documentation formats makes it even harder. Belive me, if design changes can be documented with a few simple modifications of a text file, I will start doing it.

This has the effect that documentation evolves together with the code. Add version control to the mix and pull requests suddenly become self-documenting. Furthermore, switching to Graphviz means no longer spending hours layouting documents. Time better spent doing actual design work.

With PlantUML you can document without proprietary file mongering software or an overpriced vector graphic editor. In case you ask yourself what all that fuzz is about. You create your design documents in PowerPoint and you are happy with it - Then you should probably ask yourself when things started to go wrong in you life.

Learn PlantUML You will find another Alice

Show source
@startuml
(*) --> If "Do you know PlantUML?" then
  --> [No] "Learn PlantUML"
  If "" then
    --> [I don't\nhave time] "Leave Alice"
    --> "Learn PlantUML"
  else
    --> [Ok] "Good"
  EndIf
else
--> [Yes] "Good"
EndIf
--> "Parse it"
@enduml

You are now completely convinced and/or you already created a lot of documentation in PlantUML. Good. But at some point you might like to get even more from that the language. So why not start parsing it?

Parsing PlantUML with TypeScript

Parsing the syntax to something machine-processable is easy with the command line plantuml-parser.

Show example
$ npm install -g plantuml-parser
$ plantuml-parser <<EOF
> @startuml
> package "Wonderful world without Alice" {
>   file Doc
>   file JSON
>   interface PlantUML
>   component "plantuml-parser" as pp
>
>   Doc -right- PlantUML
>   PlantUML ..> pp
>   pp -left-> JSON
> }
> @enduml
> EOF
[
  {
    "elements": [
      {
        "name": "Wonderful world without Alice",
        "title": "Wonderful world without Alice",
        "type": "package",
        "elements": [
          {
            "name": "PlantUML",
            "title": "PlantUML",
            "members": []
          },
          {
            "name": "pp",
            "title": "plantuml-parser"
          },
          {
            "left": "Doc",
            "right": "PlantUML",
            "leftType": "Unknown",
            "rightType": "Unknown",
            "leftArrowHead": "",
            "rightArrowHead": "",
            "leftArrowBody": "-",
            "rightArrowBody": "-",
            "leftCardinality": "",
            "rightCardinality": "",
            "label": "",
            "hidden": false
          },
          {
            "left": "PlantUML",
            "right": "pp",
            "leftType": "Unknown",
            "rightType": "Unknown",
            "leftArrowHead": "",
            "rightArrowHead": ">",
            "leftArrowBody": ".",
            "rightArrowBody": ".",
            "leftCardinality": "",
            "rightCardinality": "",
            "label": "",
            "hidden": false
          },
          {
            "left": "pp",
            "right": "JSON",
            "leftType": "Unknown",
            "rightType": "Unknown",
            "leftArrowHead": "",
            "rightArrowHead": ">",
            "leftArrowBody": "-",
            "rightArrowBody": "-",
            "leftCardinality": "",
            "rightCardinality": "",
            "label": "",
            "hidden": false
          }
        ]
      }
    ]
  }
]

But today we want to have a look at the programmatic use of the parser. Therefore I created the following demonstration which shows how easy it is to parse PlantUML in TypeScript. The demonstration also contains an example on how type guards can leverage processing of diagrams.

Show source
let diag = `
@startuml
class Alice <<single>> {
  +cry(): any
}
note left of Alice::cry
Untyped. She
does not like types
end note
@enduml
`

// importing the parser
import {parse, Class, Note} from 'plantuml-parser';

// for each diagram parsed
for ( let d of parse(diag) ){
  // extract all elements
  let elems = d.elements;
  for ( let e of elems ) {
    // we can use type guards to
    // distinguish between the different
    // elements in the diagram
    if ( e instanceof Class) {
      console.log('Class: '+ e.name);
    }
    if ( e instanceof Note ){
      console.log('Note on '+e.of);
    }
  }
}

Contribute

If you do like the project and you would like to contribute, there are numerous ways how you can do so. Even if you do not write source code. Every contribution counts.

Thank you.

Related Posts