tools/myna_mustache_expander.js
function expandAst(ast, data, lines) {
    if (lines == undefined)
        lines = [];
    
    // If there is a child "key" get the value associated with it. 
    let keyNode = ast.child("key");
    let key = keyNode ? keyNode.allText : "";
    let val = data ? (key in data ? data[key] : "") : "";

    // Functions are not supported
    if (typeof(val) == 'function')
        throw new Exception('Functions are not supported');

    switch (ast.rule.name) 
    {
        case "document":    
        case "sectionContent":
            ast.children.forEach(function(c) { 
                expandAst(c, data, lines); });
            return lines;

        case "comment":
            return lines;

        case "plainText":
            lines.push(ast.allText);
            return lines;

        case "section":        
            let content = ast.child("sectionContent");
            if (typeof val === "boolean" || typeof val === "number" || typeof val === "string") {
                if (val) 
                    expandAst(content, data, lines);
            }
            else if (val instanceof Array) {
                for (let x of val)
                    expandAst(content, mergeObjects(data, x), lines);
            }                
            else {
                expandAst(content, mergeObjects(data, val), lines);
            }
            return lines;

        case "invertedSection":
            if (!val || ((val instanceof Array) && val.length == 0))
                expandAst(ast.child("sectionContent"), data, lines);
            return lines;

        case "escapedVar":
            if (val) 
                lines.push(
                    expand(escapeHtmlChars(String(val)), data));
            return lines;
        
        case "unescapedVar":
            if (val) 
                lines.push(
                    expand(String(val), data));
            return lines;
    }
            
    throw "Unrecognized AST node " + ast.rule.name;
}
function expandAst(ast, data, lines) {
    if (lines == undefined)
        lines = [];
    
    // If there is a child "key" get the value associated with it. 
    let keyNode = ast.child("key");
    let key = keyNode ? keyNode.allText : "";
    let val = data ? (key in data ? data[key] : "") : "";

    // Functions are not supported
    if (typeof(val) == 'function')
        throw new Exception('Functions are not supported');

    switch (ast.rule.name) 
    {
        case "document":    
        case "sectionContent":
            ast.children.forEach(function(c) { 
                expandAst(c, data, lines); });
            return lines;

        case "comment":
            return lines;

        case "plainText":
            lines.push(ast.allText);
            return lines;

        case "section":        
            let content = ast.child("sectionContent");
            if (typeof val === "boolean" || typeof val === "number" || typeof val === "string") {
                if (val) 
                    expandAst(content, data, lines);
            }
            else if (val instanceof Array) {
                for (let x of val)
                    expandAst(content, mergeObjects(data, x), lines);
            }                
            else {
                expandAst(content, mergeObjects(data, val), lines);
            }
            return lines;

        case "invertedSection":
            if (!val || ((val instanceof Array) && val.length == 0))
                expandAst(ast.child("sectionContent"), data, lines);
            return lines;

        case "escapedVar":
            if (val) 
                lines.push(
                    expand(escapeHtmlChars(String(val)), data));
            return lines;
        
        case "unescapedVar":
            if (val) 
                lines.push(
                    expand(String(val), data));
            return lines;
    }
            
    throw "Unrecognized AST node " + ast.rule.name;
}
function expandAst ( ast , data , lines ) { if ( lines == undefined ) lines = [ ] ; // If there is a child "key" get the value associated with it.  let keyNode = ast . child ( "key" ) ; let key = keyNode ? keyNode . allText : "" ; let val = data ? ( key in data ? data [ key ] : "" ) : "" ; // Functions are not supported if ( typeof ( val ) == 'function' ) throw new Exception ( 'Functions are not supported' ) ; switch ( ast . rule . name ) { case "document" : case "sectionContent" : ast . children . forEach ( function ( c ) { expandAst ( c , data , lines ) ; } ) ; return lines ; case "comment" : return lines ; case "plainText" : lines . push ( ast . allText ) ; return lines ; case "section" : let content = ast . child ( "sectionContent" ) ; if ( typeof val === "boolean" || typeof val === "number" || typeof val === "string" ) { if ( val ) expandAst ( content , data , lines ) ; } else if ( val instanceof Array ) { for ( let x of val ) expandAst ( content , mergeObjects ( data , x ) , lines ) ; } else { expandAst ( content , mergeObjects ( data , val ) , lines ) ; } return lines ; case "invertedSection" : if ( ! val || ( ( val instanceof Array ) && val . length == 0 ) ) expandAst ( ast . child ( "sectionContent" ) , data , lines ) ; return lines ; case "escapedVar" : if ( val ) lines . push ( expand ( escapeHtmlChars ( String ( val ) ) , data ) ) ; return lines ; case "unescapedVar" : if ( val ) lines . push ( expand ( String ( val ) , data ) ) ; return lines ; } throw "Unrecognized AST node " + ast . rule . name ; }
Given an AST node, a data object, and an optional array of string, converts the nodes expanding the reserved characters.
Given an AST node a data object and an optional array of string converts the nodes expanding the reserved characters .