Giter VIP home page Giter VIP logo

aihtml's Introduction

aihtml

A simple html render libary more than Mustache Template Complier

Erlang Mustache Template

Mustache is a framework-agnostic templating system that enforces separation of view logic from the template file. Indeed, it is not even possible to embed logic in the template. This allows templates to be reused across language boundaries and for other language independent uses.

Working with Mustache means dealing with templates, views, and contexts. Templates contain HTML (or some other format) and Mustache tags that specify what data to pull in. A template can be either a string or a file (usually ending in .mustache). Views are Erlang modules that can define functions that are called and provide the data for the template tags. A context is an Erlang dict that contains the current context from which tags can pull data. A few examples will clarify how these items interact.

Installation

aihtml uses erlang.mk as its building tool. So currently, it only support erlang.mk.

Difference between bbmustache

The target of aihtml is to help user to build a simple view engine in the Erlang. And aihtml uses a modified version muatche compiler from bbmustache. But there are some difference between bbmustache.

bbmustahce:

  • It supports the standards mustache sytanx.
  • Very light, it won't create any process or ets.
  • It can compile mustache file or render directly.
  • It can render mustache string directly.

aihtml:

  • It also supports the standards mustache sytanx.
  • It adds lamda section on mustache sytanx.
  • Very heavy, it will create a process and use an ets to store some information.
  • It must compile mustache file before rendering, and store the compile result in the ets for resusing.
  • It can't render mustache string directly.

How to use

Incompatible Changes

In v0.3.5 we start using the atom key to replace the binary key of tags. So when using v0.3.5 or above, please use atom keys in context to render the templates.

Bootstrap

aihtml has to bootstrap before rendering mustache files.

It boostraps using function ai_mustache:bootstrap, it will using views directory as default directory where the mustache files are stored. And will compile all mustache files with the suffix .mustache into IR code and store them in ets.

bootstrap()-> ai_mustache_loader:bootstrap().

And there is a function which can accept one params settings to change default settings.

bootstrap(Settings) -> ai_mustache_loader:bootstrap(Settings).
Settings :: #{ 
    views :=  binary(),
    suffix := binary()
}.

Render Templates

Context

aihtml only support maps as context params when it render a mustache file. And the key must be a binary.

#{
    <<"user">> => #{
        <<"name">> => "David Gao",
        <<"level">> => 1
    },
    <<"stars">> => 10
}

Partials

aihtml supports partials, and it will auto load the partial mustache file from views directory which can be modified by bootstrap.

{{> shared/user }}

If we use the default settings, aihtml will load user.mustache from views/shared directory auto.

Sections

Section in context is a list

friends.mustache

<ul> 
  {{# friends }}
    <li>
        <img src="{{{ friends.avatar }}}"/>
        <span>{{ friends.name }}</span>
    </li>
  {{/ friends }}
</ul>

friends_context.erl

Context = #{
    <<"friends">> => [
        #{<<"name">> => "Jane", <<"avatar">> => "/images/avatar/    jane.png" },
        #{<<"name">> => "David", <<"avatar">> => "/images/avatar/    David.png" },
    ]
}

Section in context is fun/2 The first param of function will be the rendered binary inside the section.

friends.mustache

{{# warpped }}
<ul> 
 {{# friends }}
    <li>
        <img src="{{{ friends.avatar }}}"/>
        <span>{{ friends.name }}</span>
    </li>
 {{/ friends }}
</ul>
{{/ warpped}}

friends_context.erl

warpped(Acc,Context) -> <<"<div> ",Acc/binary," </div>" >>.
Context = #{
    <<"friends">> => [
        #{<<"name">> => "Jane", <<"avatar">> => "/images/avatar/    jane.png" },
        #{<<"name">> => "David", <<"avatar">> => "/images/avatar/    David.png" },
    ],
    <<"warpped">> => fun warpped/2
}

Inverted Sections

Inverted section in context is a list or not exsist

friends.mustache

{{^ friends }}
  <div> Want to know some new friends ? </div>
{{/ friends }}

friends_context.erl

Context = #{
    <<"friends">> => []
}

or

Context = #{}

Has Section

Has section in context is map

navbar.mustache

{{+ user }}
    <div>
        <span>{{user.name}}</span>
        <span>{{user.level}}</span>
    </div>
{{/ user }}

navbar_context.erl

#{
    <<"user">> => #{
        <<"name">> => "David Gao",
        <<"level">> => 1
    }
}

Has section in context is bool or binary

friends.mustache

{{+ has_friends }}
<ul> 
 {{# friends }}
    <li>
        <img src="{{{ friends.avatar }}}"/>
        <span>{{ friends.name }}</span>
    </li>
 {{/ friends }}
</ul>
{{/ has_friends}}

friends_context.erl

Context = #{
    <<"friends">> => [
        #{<<"name">> => "Jane", <<"avatar">> => "/images/avatar/    jane.png" },
        #{<<"name">> => "David", <<"avatar">> => "/images/avatar/    David.png" },
    ],
    <<"has_friends">> => true
}

Has section in context is fun/1

friends.mustache

{{+ has_friends }}
<ul> 
  {{# friends }}
    <li>
      <img src="{{{ friends.avatar }}}"/>
      <span>{{ friends.name }}</span>
    </li>
  {{/ friends }}
</ul>
{{/ has_friends}}

friends_context.erl

has_friends(Context) ->
    case maps:get(<<"friends>>,Context, undefined) of 
        undefined -> false;
        _ -> true
    end.
Context = #{
    <<"friends">> => [
        #{<<"name">> => "Jane", <<"avatar">> => "/images/avatar/    jane.png" },
        #{<<"name">> => "David", <<"avatar">> => "/images/avatar/    David.png" },
    ],
    <<"has_friends">> => fun has_friends/1
}

Inverted Has Section

Inverted has section in context is bool

friends.mustache

{+ has_friends }}
<ul> 
 {{# friends }}
    <li>
        <img src="{{{ friends.avatar }}}"/>
        <span>{{ friends.name }}</span>
    </li>
 {{/ friends }}
</ul>
{{/ has_friends}}
{{- has_friends }}
    <div> Want to know some new friends ? </div>
 {{/ has_friends }}

friends_context.erl

Context = #{
    <<"friends">> => [
        #{<<"name">> => "Jane", <<"avatar">> => "/images/avatar/    jane.png" },
        #{<<"name">> => "David", <<"avatar">> => "/images/avatar/    David.png" },
    ],
    <<"has_friends">> => true
}

Inverted has section in context is fun/1

friends.mustache

{{+ has_friends }}
<ul> 
 {{# friends }}
    <li>
        <img src="{{{ friends.avatar }}}"/>
        <span>{{ friends.name }}</span>
    </li>
 {{/ friends }}
</ul>
{{/ has_friends}}
{{- has_friends }}
    <div> Want to know some new friends ? </div>
{{/ has_friends }}

friends_context.erl

has_friends(Context) ->
    case maps:get(<<"friends>>,Context, undefined) of 
        undefined -> false;
        _ -> true
    end.
Context = #{
    <<"friends">> => [
        #{<<"name">> => "Jane", <<"avatar">> => "/images/avatar/    jane.png" },
        #{<<"name">> => "David", <<"avatar">> => "/images/avatar/    David.png" },
    ],
    <<"has_friends">> => fun has_friends/1
}

lambda

This is an extends of aihtml on mustach syntax.

Lambda in context is fun/1 layout.mustache

{{* yield}}

layout_context.erl

yield(Context) ->  ......

Context = #{
    <<"yield">> => fun yield/1
}

Lambda in context is fun/2 and a value

layout.mustache

{{* yield}}

layout_context.erl

yield(Template,Context)->
    ai_mustache:render(Template,Context).
render(Template,State) -> 
    Context = maps:get(context,State,#{}),
    Layout = maps:get(layout,State,<<"layout/default">>),
    LayoutContext = Context#{ <<"yield">> => [fun yield/2,Template] },
    ai_mustache:render(Layout,LayoutContext).

Projects who use this

aihtml's People

Contributors

davidalphafox avatar sztheory avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

aihtml's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.