2018年12月18日 星期二

javascript 另一種模板編組

function compile(template) {
    const evalExpr = /<%=(.+?)%>/g;
    const expr = /<%([\s\S]+?)%>/g;
    template = template.replace(evalExpr, '`); \n echo( $1 ); \n echo(`');
    template = template.replace(expr, '`); \n $1 \n echo(`');
    template = 'echo(`' + template + '`);';

    console.log(template);

    let script =
        `let output = "";
            function echo(html){
            output += html;
            }       
        ${template}
        return output;`;
    return new Function(script);
}


let content = "<ul>\
    <% for(let i=0; i < 4; i++){ %>\
        <li><%= i %>--${i*2}</li>\
    <% } %>\
</ul>";

let res = compile(content);
console.log(res());
console.log('--------------------');
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
https://johnresig.com/blog/javascript-micro-templating/

function compile(template) {
    let functionStr = compile_1(template);

    functionStr = "data = data || {};\n\
        for(let k in data){\n\
            let command = 'var '+ k + '= data[\"'+k+'\"];';\n\
            eval(command);\n\
        }\n\
    " + functionStr;

    console.log(functionStr);
    let fun = new Function('print', 'data', functionStr);

    function print(html) {
        return html;
    }

    return (fun).bind(null, print);
}

function compile_1(template) {
    const expr = /([\s\S]*?)<%([\s\S]+?)%>/g;
    const evalExpr = /([\s\S]*?)<%=([\s\S]+?)%>/g;

    reg_1 = /<%[^=-][\s\S]+?%>/;
    reg_2 = /<%=[\s\S]+?%>/;
    reg_3 = /<%-[^-][\s\S]+?%>/;

    let reg = [];
    reg.push("(" + reg_1.source + ")");
    reg.push("(" + reg_2.source + ")");
    reg.push("(" + reg_3.source + ")");
    reg = reg.join("|");
    reg = `([\\s\\S]*?)(?:${reg})`;
    console.log(reg);
    reg = RegExp(reg, 'g');

    let source = "let source = [];\n";
    template = template.replace(reg, function (m, g1, g2, g3, g4) {
        debugger;
        if (g1) {
            source += `source.push(\`${g1}\`);\n`;
        }

        if (g2) {
            // <% %>
            g2 = g2.replace(/%>$/, '').replace(/^<%/, '');
            source += `\n${g2}\n`;
        } else if (g3) {
            // <%= %>
            g3 = g3.replace(/%>$/, '').replace(/^<%=/, '');
            source += `source.push(print(${g3}));\n`;
        } else if (g4) {
            // <%- %>
            g4 = g4.replace(/%>$/, '').replace(/^<%-/, '');
            source += `source.push(print(${g4}));\n`;
        }

        return '';
    });

    if (template) {
        source += `source.push(\`${template}\`);\n`;
    }

    source += 'return (source.join(""));\n';

    return source;
}


let content = "<ul>\
    <% for(let i=0; i < a.length; i++){ %>\
        <li><%= i*2 %>--${a[i]*2}</li>\
    <% } %>\
</ul>";


let res = compile(content);

console.dir(res);