Skip to content

Instantly share code, notes, and snippets.

@jimeh
Created March 15, 2010 11:41
Show Gist options
  • Save jimeh/332765 to your computer and use it in GitHub Desktop.
Save jimeh/332765 to your computer and use it in GitHub Desktop.
mustache.js — Super-simple Mustache-style text-replacement.
/*
Super-simple Mustache-style text-replacement.
Example:
var data = {name: "James", location: "Mars"};
mustache("Welcome to {{location}}, {{ name }}.", data); // => Welcome to Mars, James.
*/
function mustache(string, data){
if (typeof(string) === "string" && typeof(data) === "object") {
for (var key in data) {
string = string.replace(new RegExp("{{\\s*" + key + "\\s*}}", "g"), data[key]);
}
};
return string;
};
@etgrieco
Copy link

This is a great script that even helped me 9 years later! In ES6 for those in a more modern environment:

const mustache = (string, data = {}) =>
  Object.entries(data).reduce((res, [key, value]) => res.replace(new RegExp(`{{\\s*${key}\\s*}}`, "g"), value), string);

@xyzshantaram
Copy link

Borrowed from @etgrieco's version to make this, it supports escaping via backslashes.
(This is TypeScript ofc, you'd remove the annotations from the function signature to make it regular JS)

const mustache = (string: string, data: Record<string, object> = {}) => {
    return Object.entries(data).reduce((res, [key, value]) => {
        // lookbehind expression, only replaces if mustache was not preceded by a backslash
        const mainRe = new RegExp(`(?<!\\\\){{\\s*${key}\\s*}}`, 'g')
        // this regex is actually (?<!\\){{\s*<key>\s*}} but because of escaping it looks like that...
        const escapeRe = new RegExp(`\\\\({{\\s*${key}\\s*}})`, 'g')
        // the second regex now handles the cases that were skipped in the first case.
        return res.replace(mainRe, value.toString()).replace(escapeRe, '$1');
    }, string);
}
const data  = {name: "James", location: "Mars"};
// note that the double backslash is only since this is a JS string constant
mustache("Welcome to \\{{ location }}, {{ name }}.", data);
// result: "Welcome to {{ location }}, James."

@nitrique
Copy link

nitrique commented Apr 6, 2022

@xyzshantaram Regex are not very user friendly, I suggest using this instead:

export const mustache = (string: string, data: Object) => Object.entries(data).reduce((res, [key, value]) => {
  const search = `{${key}}`

  if (
    res.indexOf(search) !== -1 &&
    res.indexOf(`\\${key}`) == -1 && // Escaped on start
    res.indexOf(`${key}\\`) == -1 // Escaped on end
  ) {
    return res.replace(search, value)
  }

  return res
}, string)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment