**NAME** dia2kroki - convert textual descriptions for various diagram tools to image URL's using the https://kroki.io/ webservice. <> **CODE** ====== # dia2kroki.tcl proc dia2kroki {text {dia graphviz} {ext svg}} { set b64 [string map {+ - / _ = ""} [binary encode base64 [zlib compress $text]]] set uri https://kroki.io//$dia/$ext/$b64 } # like to know the code of an URL proc kroki2dia {url} { set text [regsub {.+/} $url ""] set dia [zlib decompress [binary decode base64 [string map {- + _ /} $text]]] } ====== **EXAMPLES** ***dia2kroki*** ====== % source dia2kroki.tcl % puts [dia2kroki "digraph G { A -> B }"] https://kroki.io//graphviz/svg/eJxLyUwvSizIUHBXqFZwVNC1U3BSqAUAREAFzQ ====== This URL can be directly embedded into HTML pages or on Markdown code. Unfortunately as far as I know Tcler's Wiki can't embed external images without an extension like png, svg etc. So just the link to the image is shown. https://kroki.io//graphviz/svg/eJxLyUwvSizIUHBXqFZwVNC1U3BSqAUAREAFzQ To fix this we have to use the ''inlinehtml'' syntax: ====== <> . <> ====== Here the output: <> . <> Here an example for plantuml: http://www.plantuml.com ====== % source dia2kroki.tcl % dia2kroki { @startuml Bob -> Alice : hello @enduml } plantuml png https://kroki.io//plantuml/png/eJzjciguSSwqKc3N4XLKT1LQtVNwzMlMTlWwUshIzcnJ53JIzUsBSQIABnMM1A ====== Here this image, this time a PNG: <> <> ***kroki2dia*** Using `kroki2dia` you can get the code of an kroki URL back to text: ====== % kroki2dia https://kroki.io//graphviz/svg/eJxLyUwvSizIUHBXqFZwVNC1U3BSqAUAREAFzQ digraph G { A -> B } ====== **GUI** Let's build around those two functions a graphical user interface where you can enter your diagram code in a text widget, after file saving the extensions determines the diagram type and the data are send to the server. The produced image ist then fetched to to local machine and displayed in a ttk::label below. For tools like [Pikchr] which can only create SVG images [cairosvg] is required to convert the image then locally to png: ====== namespace eval ::kroki { } proc ::kroki::dia2kroki {text {dia graphviz} {ext svg}} { set b64 [string map {+ - / _ = ""} [binary encode base64 [zlib compress $text]]] set uri https://kroki.io//$dia/$ext/$b64 } proc ::kroki::kroki2dia {url} { set text [regsub {.+/} $url ""] set dia [zlib decompress [binary decode base64 [string map {- + _ /} $text]]] } proc ::kroki::gui {{path ""}} { package require Tk variable txt variable img variable lastfile variable filetypes variable maps ttk::frame $path.top foreach btn [list New Open Save SaveAs Exit] { ttk::button "$path.top.[string tolower $btn]" -width 10 -text $btn -command ::kroki::file$btn pack "$path.top.[string tolower $btn]" -side left -padx 5 -pady 5 } pack $path.top -side top ttk::panedwindow $path.pwd -orient horizontal ttk::frame $path.pwd.frame ttk::label $path.pwd.frame.lbl -text "Hello" place $path.pwd.frame.lbl -relx 0.5 -rely 0.5 -anchor center tk::text $path.pwd.text $path.pwd add $path.pwd.text $path.pwd add $path.pwd.frame pack $path.pwd -side top -fill both -expand true # variables set txt $path.pwd.text set img $path.pwd.frame.lbl set lastfile "" set filetypes { {{BlockDiag Files} {.bdia} } {{Ditaa Files} {.ditaa} } {{Graphviz Files} {.dot} } {{Mermaid Files} {.mmd} } {{Pikchr Files} {.pik} } {{PlantUML Files} {.puml} } {{SeqDia Files} {.sdia} } {{All Files} * } } set maps [dict create bdia blockdiag ditaa ditaa dot graphviz puml plantuml \ mmd mermaid pik pikchr sdia seqdiag] # bindings bind $txt ::kroki::fileSave # styles ttk::style layout WLabel [ttk::style layout TLabel] ttk::style layout WFrame [ttk::style layout TFrame] ttk::style configure WLabel -background white ttk::style configure WFrame -background white $img configure -style WLabel $path.pwd.frame configure -style WFrame } proc ::kroki::fileNew {} { variable txt variable lastfile "" $txt delete 1.0 end } proc ::kroki::fileSave {} { variable lastfile variable txt variable maps variable img if {$lastfile eq ""} { ::kroki::fileSaveAs return } if {$lastfile ne ""} { set text [$txt get 1.0 end] set out [open $lastfile w 0600] puts $out "$text" close $out set ext [string range [file extension $lastfile] 1 end] if {![dict exists $maps $ext]} { tk_messageBox -title "Error!" -icon error -message "Wrong file extension `.$ext`!\nUse .dot, .mmd, .puml or .pik!" -type ok return } if {$ext eq "pik"} { if {[auto_execok cairosvg] eq ""} { tk_messageBox -title "Error!" -icon error \ -message "Error: Pikchr diagrams need cairosvg!\nPlease install: pip3 install cairosvg --user" \ -type ok return } set uri [::kroki::dia2kroki $text [dict get $maps $ext] svg] puts "fetching $uri" exec -ignorestderr wget $uri -O [file rootname $lastfile].svg 2>&1 exec -ignorestderr cairosvg -f png -o [file rootname $lastfile].png [file rootname $lastfile].svg } else { set uri [::kroki::dia2kroki $text [dict get $maps $ext] png] puts "fetching $uri" exec -ignorestderr wget $uri -O [file rootname $lastfile].png 2>&1 } if {[file exists [file rootname $lastfile].png]} { image create photo ::kroki::img -file [file rootname $lastfile].png $img configure -image ::kroki::img } wm title . "kroki-gui [file tail $lastfile]" } } proc ::kroki::fileSaveAs {} { variable filetypes variable txt variable lastfile set types $filetypes unset -nocomplain savefile set savefile [tk_getSaveFile -filetypes $types] if {$savefile != ""} { set lastfile $savefile ::kroki::fileSave } } proc ::kroki::fileOpen {{filename ""}} { variable txt variable lastfile variable filetypes set types $filetypes if {$filename eq ""} { set filename [tk_getOpenFile -filetypes $types] } if {$filename != ""} { $txt delete 1.0 end if [catch {open $filename r} infh] { puts stderr "Cannot open $filename: $infh" exit } else { while {[gets $infh line] >= 0} { $txt insert end "$line\n" } close $infh } set lastfile $filename } } proc ::kroki::fileExit {} { set answer [tk_messageBox -title "Question!" -message "Really exit ?" -type yesno -icon question] if { $answer } { exit 0 } } if {[info exists argv0] && $argv0 eq [info script]} { kroki::gui if {[llength $argv] > 0} { if {[file exists [lindex $argv 0]]} { ::kroki::fileOpen [lindex $argv 0] ::kroki::fileSave } } } ====== Here two example images for the running application first editing https://github.com/drhsqlite/pikchr%|%Pikchr%|% code: <> <> And then, if you prefer more the old ASCII style - you can create a http://ditaa.sourceforge.net/%|%ditaa%|% image: [kroki-gui-ditaa] ---- **DISCUSSION** Please discuss here. [DDG] - 2022-02-18: The main advantage of this little function is that you can create these images without having all these diagram tools installed just using basic Tcl (8.6). You can embed the images directly into your documentation using a simple hyperlink or you can download the images using Tcl with the [http] and [tls] libraries or a tool like wget.