jeyson

Json template engine

Usage no npm install needed!

<script type="module">
  import jeyson from 'https://cdn.skypack.dev/jeyson';
</script>

README

Jeyson Templates

  • Every json is a valid template in itself.
  • The templates can have expressions, which can execute javascript.
  • These templates are compiled in context of a scope.
  • Directives can pass instructions to compiler.
  • Inbuilt directives for repeating, including other json etc.
  • Custom directives can replace/modify template body, execute expressions, read other templates.

Compiling Templates

var jeyson        = require('jeyson').create(),
    scope         = {message: 'Hello!'},
    templateJson  = {"message": "{{message}}"},
    compiled      = jeyson.compile(scope, templateJson);

Expressions

An expression is defined as '{{expr}}'

Following template.json :

{
  "age": "{{21 + 33}}"
}

is compiled to

{
 "age": 54
}

Javascript in Expressions.

Any valid javascript snippet is a valid expression, e.g following template.json :

{
  "list"      : "{{'one,two,three,four,five'.split(',')}}",
}

is compiled to

{
 "list"    : ["one", "two", "three", "four", "five"],
}

Scopes

Any field on scope object, is available as local variable in expressions.

e.g. Given scope defined as :

var scope    = {message: "Hello !"},

then following template.json :

{
  "message": "{{message}}"
}

is compiled to

{
 "message": "Hello !"
}

Scope can have methods

e.g. Given scope defined as :

var scope = {
   message: function(){
     return "Hello !";
   }
};

then following template.json :

{
  "message": "{{message()}}"
}

is compiled to

{
 "message": "Hello !"
}

Directives

  • Directive is a field with name starting with "@"
  • Directive body is the parent subtree of directive field
  • Directive argument is the value of directive field.

E.g.

{
   "list"  : {
     "@repeat" : "name in ['one','two','three','four','five']",
     "id"      : "{{$index + 1}}",
     "name"    : "{{name}}",
   }
}
  • "list" value is directive body (has a directive child)
  • @repeat is directive name
  • count in [1,2,3,4,5] is directive argument

It will compile to following json :

{
  "list": [ {"id": "1","name" : "one"},
            {"id": "2","name" : "two"},
            {"id": "3","name" : "three"},
            {"id": "4","name" : "four"},
            {"id": "5","name" : "five"}];
}

Conditional Blocks & System Directives

Following are the conditional directives

  1. switch
  2. if
  3. ignore-if (a system directive)

@switch

Will replace the body with "@[value]", "@default" or null based on choice.

scope    = {role : {name: "admin"}}
template = {
"user"    : {
  "role"    : {
     "@switch"    : "role.name",
     "@admin"     : {"name" : "admin"},
     "@visitor"   : {"name" : "visitor"},
     "@default"   : {"name" : "guest"}
  }
}

Will compile to

template = {
   "user"   : {
   "role"  : {"name" : "admin"}
 }

@if, @then, @else

Will set field value to null, "@then" or "@else", by condition

{
  "author"  : "ABC",
  "book"    : {
    "@if"   : "1 == 2",
    "@then" : {"title" : "Harry Potter"}
    "@else" : "unknown",
  }
}

will result in

{
 "author"  : "ABC",
 "book"    : "unknown"
}
{
  "author"  : "ABC",
  "book"    : {
    "@if"   : "1 == 1",
    "@then" : {"title" : "Harry Potter"}
}

will result in

{
 "author"  : "ABC",
 "book"    : {"title" : "Harry Potter"}
}
{
  "author"  : "ABC",
  "book"    : {
    "@if"   : "1 == 2",
    "@then" : {"title" : "Harry Potter"}
}

will result in

{
 "author"  : "ABC",
 "book"    : null
}

@ignore-if

Will not render the field itself, if the condition is false.

e.g

{
  "author"  : "ABC",
  "book"    : {
    "@ignore-if": "1 == 1",
    "title"     : "Harry Potter"
  }
}

will result in

{
 "author"  : "ABC"
}

Inbuilt Directives

Inbuilt directives for repeating, including other json etc.

@repeat

  • $index
  • array
  • result

Custom Directives

  • Reading scope
  • Executing expressions
  • Modifying body
  • Replacing body
  • Reading other templates by relative path

Source code of inbuilt directives