**NAME** dia2plantuml - convert textual descriptions for various diagram tools to image URL's using the https://www.plantuml.com/ server. <> **CODE** ====== #!/usr/bin/env tclsh package provide plantuml2dia 0.1 ### file dia2plantuml.tcl proc dia2plantuml {text {ext svg}} { ### plantuml does use a different order in encoding set b64 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ set pml 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_ set lmapper [list] set i 0 foreach char [split $b64 ""] { lappend lmapper $char lappend lmapper [string range $pml $i $i] incr i } set b64 [string map $lmapper [binary encode base64 [zlib compress [encoding convertto utf-8 $text]]]] set uri https://www.plantuml.com/plantuml/$ext/~1$b64 return $uri } ### converting URL to diagram code back proc plantuml2dia {uri} { set b64 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ set pml 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_ set lmapper [list] set i 0 foreach char [split $pml ""] { lappend lmapper $char lappend lmapper [string range $b64 $i $i] incr i } set text [regsub {.+/} $uri ""] set text [regsub {^~1} $text ""] set dia [encoding convertfrom utf-8 [zlib decompress [binary decode base64 [string map $lmapper $text]]]] } ### make it a standalone application if {[info script] eq $argv0} { proc usage {} { puts "Usage: $::argv0 plantuml-url|diagra-file" } proc help {} { puts "PlantUML encoder/decoder" puts "Converts PlantUML code in files to PlantUML URLS or" puts "converts PlantUML URL's back to diagram code." puts "Note: Only URLS with the ~1 prefixes can be currently encoded back!" puts "Author: Detlef Groth, University of Potsdam, Germany" puts "License: BSD 3.0" puts "" usage } if {[llength $argv] == 0} { usage } elseif {[info exists argv] && "--help" in $argv} { help } elseif {[llength $argv] == 1} { if {[regexp {^http} [lindex $argv 0]]} { if {![regexp "~1" [lindex $argv 0]]} { puts "Error: Only URL's with ~1 inside can be decoded!" } else { puts -nonewline [plantuml2dia [lindex $argv 0]] } } else { if {![file exists [lindex $argv 0]]} { puts "Error: File '[lindex $Eargv 0]' does not exists!" } else { if [catch {open [lindex $argv 0] r} infh] { puts stderr "Cannot open [lindex $argv 0]e: $infh" exit } else { set text [read $infh] puts -nonewline [dia2plantuml $text] } } } } } ====== This code was translated from Python to Tcl, for the Python code look here: https://github.com/dougn/python-plantuml/blob/master/plantuml.py - the encoding used by PlantUML is explained here: https://plantuml.com/text-encoding **EXAMPLES** ====== % source dia2plantuml.tcl % puts [dia2plantuml "class TclExample"] https://www.plantuml.com/plantuml/svg/~1U9nBpaaiBbO8ISvnhKZCBSX91G0pUGOc % puts [plantuml2dia [dia2plantuml "class TclExample"]] TclExample ====== Here the image: <> . <> Here now a run as a standalone application: ====== ### make a test file $ echo -e "class A {}\nclass B {}\nA -> B" > class.pml ### encode it as URL (image below) $ dia2plantuml.tcl class.pml https://www.plantuml.com/plantuml/svg/~1U9nBpaaiBbPmLAYkvKe6Cvr0J4S5NJi59ou0Zfe8R0== ### decode it back $ dia2plantuml.tcl https://www.plantuml.com/plantuml/svg/~1U9nBpaaiBbPmLAYkvKe6Cvr0J4S5NJi59ou0Zfe8R0== class A {} class B {} A -> B ====== <> . <> **SEE ALSO** * [dia2kroki] ---- **DISCUSSION** Please discuss here. * [DDG] - 2023-07-29: decoding an URL back to diagram code now works * [DDG] - 2023-07-30: make it a standalone application and a package as well <> Graphics