metasoarous / oz

Data visualizations in Clojure and ClojureScript using Vega and Vega-lite
Eclipse Public License 1.0
829 stars 74 forks source link

Question: Clojure Functions Evaluated in Markdown #157

Open thecontinium opened 3 years ago

thecontinium commented 3 years ago

Hi

Thanks for writing a great library.

I am new to oz and I have been looking through all the examples but I have not been able to see what I would like to do. I am probably missing something :)

I would like to be able to add the contents returned from a clojure function/var in the markdown file when it is being loaded/compiled.

I understand that one can have code blocks defined as vega/vega-lite and hiccup which are added appropriately but don't see a way of evaluated clojure functions being added from inside these block or the markdown itself.

I have been able to use tag-compilers when compiling hiccup

(oz/compile
    [:div [:poop "yo dawg"]]
    {:tag-compilers {:poop (fn [_] [:blah "BLOOP"])}
     :to-format :html})

but not from hiccup in a markdown code block something like this

 # markdown

 ```edn hiccup
 [:div [:poop "yo dawg"]]
 {:tag-compilers {:poop (fn [_] [:blah "BLOOP"])}
 :to-format :html})
  ```

Some advice would be welcome.

Thanks.

metasoarous commented 3 years ago

Hi @thecontinium. Thanks for asking about this.

The proper place to specify the compilers is not in the edn/hiccup blocks, but rather in the whatever code you're using to process the markdown. Somewhere, presumably, you're compiling the markdown content using oz/compile, oz/view!, oz/build! or the like; That is where the :tag-compilers specification should go.

Please let me know if this makes sense, or if you have any further questions.

Thanks again!

thecontinium commented 3 years ago

Hi

Thanks for your reply.

To have the ability to add anything to the markdown through a Clojure function I implemented a new compile*.

In the way you have code blocks to add hiccup and/or vega(lite) I added two other markdown code block types that will evaluate the Clojure edn in the blocks and either return markdown or a hiccup code block for oz to then load. I wrote my own compile* to do this which in effect parses the md replacing the new code blocks appropriately and then loads it in the normal way. This all works well.

Maybe there is a better way? but this works well and gives a lot of flexibility to create md clojure "snippets" to add specific types of information from any source Clojure can access into the markdown. I add all the functions into a "snippets" namespace and ensure this is required before the parsing takes place. I have snippets for tables, Vega graphs loaded from databases etc.

You might consider adding additional md code blocks edn->hiccup and end->markdown to achieve this.

Cheers

metasoarous commented 3 years ago

Hi @thecontinium.

Thanks for the follow up.

First off, my apologies for not reading all of your message prior to responding. I think I was reading/writing on my phone and must have missed the first code block where you clearly illustrate that you understand the "normal" way to use the :tag-compilers.

Now that I understand that this is really what you want to do: It's on the roadmap to add a mechanism to evaluate clj (or potentially other langs) code blocks, probably by using the code block tags clj eval (etc.). This would allow you to use something like

```clj eval
(require '[oz.core :as oz])
(oz/compile
  [:div [:poop "yo dawg"]]
  {:tag-compilers {:poop (fn [_] [:blah "BLOOP"])}
   :to-format :html})
```

This is not only useful for the control of tag compilers, or for reusable snippets as you mention, but also for making Oz's markdown support a full featured markdown-based "notebook" like environment for doing data science and such (as you hint at with database calls, etc). These things don't just have to be implemented in separate files and used as tag compilers, but can just be a bunch of code for fetching or computing data inline with the markdown.

If you're interested in working on this, I'd be happy to accept a PR. There are a few design decisions to flesh out still, but we can sort these out.

Thanks again