Open nixin72 opened 4 years ago
This is easily doable. In your pollen.rkt
, create include-digraph
as follows:
#lang racket
(require graphviz)
(provide (all-defined-out))
(define (include-digraph name digraph
#:ext [ext 'png]
#:tag [tag (λ (x) `(image ,x))]
#:dir [dir "images"])
(make-directory* dir)
(define path (build-path dir (~a name (equal-hash-code digraph) "." ext)))
(unless (file-exists? path)
(send (pict->bitmap (digraph->pict (make-digraph digraph))) save-file path ext))
(tag (path->string path)))
This renders a digraph into an image file if it doesn't exist already, and then returns its path wrapped with tag
.
Then, the Pollen program:
#lang pollen
this is some text
◊(include-digraph "first-diagram"
`("v0" "v1" "v2" "v0 -> v0" "v0 -> v1" "v1 -> v2" "v2 -> v0")
#:tag (λ (img-path) `(img ([src ,img-path]))))
some more text after a picture of my FSM
would produce
'(root
"this is some text"
"\n"
"\n"
(img ((src "images/first-diagram-1065713455284007950.png")))
"\n"
"\n"
"some more text after a picture of my FSM")
The 1065713455284007950
is a (practically) unique identity of your digraph, so if you modify your digraph, it would render your digraph again. But if you make no changes to your digraph, it will reuse the existing file.
The {···}
notation will produce a list of strings, so it would also be possible to write the tag function to directly support (some subset of) DOT input:
#lang pollen
this is some text
◊include-digraph{
v0;
v1;
v2;
v0 -> v0;
v0 -> v1;
v1 -> v2;
v2 -> v0;
}
some more text after a picture of my FSM
Thank you so much! I'm pretty sure Pollen is going to become my go-to tool from now on for writing, I can't believe it's that easy to extend to include something like this!
Note: my code above will create a lot of junk files if you modify the digraph several times. One easy improvement is to read the file images/first-digraph.data
and compare it against your digraph. If they match, then skip rendering, but if it doesn't match, then update both images/first-digraph.data
and images/first-digraph.png
. I guess the main point is that you have a full power of programming here, so you can do whatever you want :)
PS. You say mixing diagrams inline with Markdown “isn't going to happen” but watch this final trick. You can use the #lang pollen/markdown
dialect and write in Markdown normally. When you get to the include-digraph
tag function, you’d need it to emit valid Markdown (instead of an X-expression, as it does now). But arbitrary HTML is valid inside a Markdown doc. So just run the output of your tag function through xexpr->html
and your dream comes true.
:open_mouth:
This is so cool... Thank you so much @mbutterick and @sorawee!
Looks like y'all have solutions, so I don't want to confuse things further, but for people looking to do more visual/graphical content inside Markdown (acknowledging how @mbutterick feels about Markdown <-:), there's Markdeep: https://casual-effects.com/markdeep/.
I don't know what it would take to incorporate into Pollen, but at least Markdeep offers something of real value, especially for diagrams, well beyond the thin veneer over HTML that Markdown is.
One thing that I've wanted out of Markdown for a really long time is the ability to draw graphviz diagrams inline with my Markdown code. Now, this isn't going to happen with Markdown, so I just draw my diagrams in graphviz and include the images normally, but this becomes a huge pain when I'm answering answering assignment questions and naming my files something like
q5-c.dot
and trying to keep track of over a dozen of them. But Racket has a Graphviz library, so I was thinking if it might be possible to achieve this with Pollen.What I want to be able to do something like:
I was wondering if this would work by first getting graphviz to generate the image and dump into into a temp file in a bin directory or something, then link to the image with an img tag or with whatever rendering strategy it's trying to use.
Is this something that Pollen can already do? I didn't read anything about it in the tutorials. If not, is it something you'd consider including?