npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

muswish

v1.0.0

Published

Muswish templating language

Downloads

11

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