kindly-render
is a Clojure library for rendering kinds as markdown or html.
Clay is for literate and interactive programming. This library was extracted from Clay to be more useful to other visual tool developers. The hope is to make it convenient to share visualizations between tools.
Kindly is a common ground for defining how things should be visualized, seeking compatibility across tools.
kindly-advice is a library that helps tools such as Clay to be Kindly-compatible.
read-kinds is used internally by Claykind (and soon by Clay as well) to generate Kindly advice from notebooks expressed as Clojure namespaces.
Claykind is rethinking the Clay architecture and implementation from scratch, in a new code base. The two projects are being developed in coordination.
Visual toolmakers may benefit from having a shared collection of viewers for the kinds defined by Kindly. Rendering visualizations should be possible in both Clojure and ClojureScript. Viewers may need to be tailored to different usage scenarios.
The purpose of this library is to take a note
or notebook
consisting of notes
,
and produce markdown, hiccup, or html for displaying them.
A note is a map containing either a value, form, or both.
Example note:
{:form (+ 1 2)
:value 3}
Example notebook:
{:notes [{:value 3} {:value "Hello world"}]}
A note may be annotated for visualization with kindly:
{:value (kind/hiccup [:svg [:circle {:r 10}]])}
(require '[scicloj.kindly-render.note.to-hiccup :as to-hiccup])
(def my-note {:value {:my "value"}})
(to-hiccup/render my-note)
Returns a hiccup representation of the visualization of my-note
.
(require '[scicloj.kindly-render.notes.to-html-page :as to-html-page])
(def my-notebook {:notes [my-note]})
(to-html-page/notes-to-html my-notebook)
Returns a string of HTML representation of the my-notebook
.
See examples/basic/page.clj for a concrete example.
Sometimes we want to produce a JavaScript enabled visualization, but sometimes we can't. Maybe we are making a PDF, and so we need to use a static image instead.
Under scicloj.kindly-render.note
are several targets:
to-hiccup
(plain)to-hiccup-js
(javascript enhanced)to-markdown
to-scittle-reagent
The main entry point for each is render
.
When making a PDF from HTML, users would call to-hiccup/render
and get an image, but when making a rich web page they might call to-hiccup-js/render
and get the JavaScript enhanced HTML instead.
render
calls kindly-advice/advise
which ensures that the input note
has a completed value.
Completion means that if note
only contained a :form
, that form would be evaluated to produce a value and added as :value
.
Furthermore, both the form and value are checked for kindly annotations as metadata, or the kind may be inferred.
At this point the note
will contain a key :kind
which indicates the visualization requested (if any).
The completed note is passed to render-advice
which is a multimethod that dispatches on the :kind
to produce the target output.
Each target has a multi-method called render-advice
with methods defined for as many :kinds
as are supported by that target.
Using multi-methods allows users to use the standard features of Clojure to add or replace viewers if they would like to.
Each multi-method has a :default
implementation.
If no viewer is matched in markdown
, it will fall back to hiccup-js
.
If no viewer is matched there, then it will fall back to hiccup
.
Fallback only happens in one direction because hiccup
cannot fall back to markdown
, but markdown
can fall back to hiccup
.
Markdown is not valid HTML, however it should be noted that hiccup may contain markdown values like (kind/md "# this is markdown")
,
these will be converted to HTML by the hiccup renderer.
Similarly plain hiccup
cannot fall back to hiccup-js
, but hiccup-js can fall back to hiccup
.
Sometimes visualizations may contain other visualizations. For example, we may wish to present a vector containing a chart and a table. Data structures may contain nest visualizations, and these in turn may contain further nesting.
Nesting kinds are: :kind/vector
, :kind/map
, :kind/set
, :kind/seq
, :kind/hiccup
and :kind/table
.
Each target multi-method must have a method for each nesting kind that calls walk/render-hiccup-recursively
.
Hiccup is a special data structure that requires a little more care. Other visualizations may be nested inside the hiccup.
Each target multi-method must have a method for :kind/hiccup
for recursively rendering that calls walk/render-hiccup-recursively
.
kind-portal
is excluded by default. In order to use Portal you will need to add it to your
deps.edn
file.
Regular updates are given at the visual-tools meetings.
The best places to discuss this project are:
- a topic thread under the #kindly-dev stream at the Clojurians Zulip (more about chat streams here)
- a github issue
- a thread at the visual-tools channel of the Clojurians slack
Copyright © 2024 Scicloj