muswish
v1.0.0
Published
Muswish templating language
Downloads
4
Maintainers
Readme
Muswish
Muswish is a new templating language writted in javascript without any dependencies
Inspiration
The README is inspired from mustache.js
Where to use ?
You can use it to render muswish templates anywhere you can use JavaScript. This includes web browsers, server-side environments such as Node.js, and CouchDB views.
Install
$ npm install muswish --save
CDN
<script src="https://unpkg.com/[email protected]/dist/index.js"></script>
Usage
Below is a quick example how to use:
const muswish = require("muswish");
const view = {
title: "Joe",
calc: function () {
return 2 + 4;
},
};
const output = muswish("{{title}} spends {{calc}}", view);
In this example, the muswish
function takes two parameters: 1) the template and 2) the data needed to render the template.
Templates
There are several techniques that can be used to load templates and hand them to muswish.js, here are two of them:
Include Templates
If you need a template for a dynamic part in a static website, you can consider including the template in the static HTML file to avoid loading templates separately. Here's a small example:
// file: render.js
const template = document.querySelector("#template").innerHTML;
const output = muswish(template, { name: "Yoann" });
document.querySelector("#target").innerHTML = output;
<html>
<body>
<div id="target">Loading...</div>
<script id="template" type="x-tmpl-muswish">
Hello {{ name }}!
</script>
</body>
<script src="https://unpkg.com/muswish@latest"></script>
<script src="render.js"></script>
</html>
Load External Templates
If your templates reside in individual files, you can load them asynchronously and render them when they arrive. Another example using fetch:
//render.js
fetch("template.muswish")
.then((response) => response.text())
.then((template) => {
const output = muswish(template, { name: "Yoann" });
document.querySelector("#target").innerHTML = rendered;
});
Variables
The most basic tag type is a simple variable. A {{name}}
tag renders the value of the name
key in the current context. If there is no such key, nothing is rendered.
If you want {{name}}
not to be interpreted as a muswish tag, but rather to appear exactly as {{name}}
in the output, you can custom the delimiters (see below);
View:
{
"name": "Yoann",
"company": "<b>GitHub</b>"
}
Template:
* {{name}}
* {{age}}
* {{company}}
Output:
* Yoann
*
* <b>GitHub</b>
View:
{
"name": {
"first": "Michael",
"last": "Jackson"
},
"age": "RIP"
}
Template:
* {{name.first}} {{name.last}}
* {{age}}
Output:
* Michael Jackson
* RIP
If statement
False Values or Empty Lists
If the person
key does not exist, or exists and has a value of null
, undefined
, false
, 0
, or NaN
, or is an empty string or an empty list, the block will not be rendered.
View:
{
"person": false
}
Template:
Shown. {{ [if] person }} Never shown! {{ [end if] person }}
Output:
Shown.
If not statement
View:
{
"error": false
}
Template:
{{ [if not] error }} No error! {{ [end if not] error }}
Output:
No error!
Non-Empty Lists
If the person
key exists and is not null
, undefined
, or false
, and is not an empty list the block will be rendered.
View:
{
"stooges": [{ "name": "Moe" }, { "name": "Larry" }, { "name": "Curly" }]
}
Template:
{{ [for] stooges }}
<b>{{ name }}</b>
{{ [end for] stooges }}
Output:
<b>Moe</b>
<b>Larry</b>
<b>Curly</b>
When looping over an array of strings, a this
can be used to refer to the current item in the list.
View:
{
"musketeers": ["Athos", "Aramis", "Porthos", "D'Artagnan"]
}
Template:
{{ [for] musketeers }}
* {{this}}
{{ [end for] musketeers }}
Output:
* Athos
* Aramis
* Porthos
* D'Artagnan
If the value of a section variable is a function, it will be called in the context of the current item in the list on each iteration. You can use a function from the original data by using [>]
operator that refer to the original data and not the current item.
View:
{
"beatles": [
{ "firstName": "John", "lastName": "Lennon" },
{ "firstName": "Paul", "lastName": "McCartney" },
{ "firstName": "George", "lastName": "Harrison" },
{ "firstName": "Ringo", "lastName": "Starr" }
],
"name": function () {
return this.firstName + " " + this.lastName;
}
}
Template:
{{ [for] beatles}}
* {{ [>] name}}
{{ [end for] beatles }}
Output:
* John Lennon
* Paul McCartney
* George Harrison
* Ringo Starr
Comments
Today{{ [@@] I m a comment }}
Yesterday{{ [@@]
I m a comment
On multiple lines
}}
Will render as follows:
Today
Yesterday
Custom delimiters
define custom delimiters:
muswish.customDelimiters("<%", "%>");
template:
{{ something }}
<% something %>
width data:
const data = { something: "Hey" };
output:
{{ something }}
Hey
Adding plugins
You can add custom operation with muswish.addPlugin
function.
Example for the for
statement:
muswish.addPlugin("for", {
open: "FOR",
close: "END FOR",
fn: function (
_m: string,
template: string,
spaceStart: string,
content: string,
data: Data, //actual data, if we are in a for it's the current item
originalData: Data, //original data (not the current item)
callback: Function //refer to muswish function for recursivity
) {
const items = getDeepObj(data, content);
if (!(items instanceof Array) || items.length === 0) return "";
return (
keepOnlyNewLine(spaceStart) +
items.map((e: Data) => callback(template, e, originalData)).join("\n")
);
},
};);
type:
export type RULE = {
open: string;
close?: string;
fn: (
_m: string,
template: string,
spaceStart: string,
content: string,
data: Data,
originalData: Data,
callback: Function
) => string;
};
example:
{{ [for] items }}
<p>{{ this }}</p>
{{ [end for] items }}
will give:
- _m
{{ [for] items }}
<p>{{ this }}</p>
{{ [end for] items }}
- template
<p>{{ this }}</p>
- spaceStart
\n\t
- content
items