Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sophicshift/ondim

Multitype expansions for easy templating
https://github.com/sophicshift/ondim

haskell heist html latex mustache pandoc template

Last synced: about 1 month ago
JSON representation

Multitype expansions for easy templating

Awesome Lists containing this project

README

        

#+title: Ondim - multitype expansions for easy templating

#+html:

Ondim is a library for creating templating engines for arbitrary formats, inspired by Heist (which only works for HTML). It also includes HTML, LaTeX and Whiskers (a new template language very similar to Mustache) targets that work out-of-the-box.

Here is an overview of features:
- You can write polymorphic template code (see below);
- It has helpers to load templates from multiple directories, in an union mount with live reload, and to load templates at compile-time;
- Very extensible, both for the templates that can be written and for the file formats supported;
- Customizable error system with backtraces;
- Reasonably fast, runs in the ST monad;
- The code base is very modular and has few dependencies.

The main idea is to reuse existing libraries that will provide the target language's parser, types and renderer, and easily build an "expansion" layer on top. If you are familiar with Heist, for HTML this is done by binding /named expansions/ (in Heist they are called Splices) that programatically transform the contents of HTML elements whose tags match the name.

For instance, this is how you could define an if/else expansion with ~Ondim~:
#+begin_src haskell
ifElse :: (OndimNode t) => Bool -> Expansion s t
ifElse cond node = do
let els = children node
yes = filter ((Just "else" /=) . identify) els
no =
maybe [] children $
find ((Just "else" ==) . identify) els
if cond
then expandSubs yes
else expandSubs no
#+end_src

Now, suppose you have a variable ~isCat :: Bool~ and you want your templates to choose between two snippets depending on its value. Such HTML template could have type ~[HtmlNode]~, so that if you expand it while binding ~ifElse isCat~ to the name ~if-cat~,

#+begin_src haskell
expandNode myTemplateContent
`binding` do
"if-cat" #* ifElse isCat
#+end_src

you can now write in your HTML templates...

#+begin_src html

I have a beautiful cat!



I don't have a cat 😭


#+end_src

...and the output will depend on the value of ~isCat~.

The beauty of ondim (and one aspect that takes it further from Heist) is that the ~ifElse~ splice is polymorphic on the format type, so the same code works for formats other than HTML. If you want to template JSON, the same code above would work if ~myTemplateContent~ had type ~[Value]~, and a similar template could be written as:
#+begin_src yaml
- $: if-cat
$children:
- I have a beautiful cat!
- $: else
$children:
- I don't have a cat 😭
#+end_src

Or TeX:
#+begin_src latex
\@ifCat{
I have a \emph{beautiful} cat!
\@else{
I don't have a cat 😭
}
}
#+end_src