| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 | /*Copyright 2012, KISSY UI Library v1.20MIT Licensedbuild time: Jan 10 19:03*//** * @fileoverview KISSY Template Engine. * @author yyfrankyy@gmail.com */KISSY.add('template/base', function(S) {    var // Template Cache        templateCache = {},        // start/end tag mark        tagStartEnd = {            '#': 'start',            '/': 'end'        },        // static string        KS_TEMPL_STAT_PARAM = 'KS_TEMPL_STAT_PARAM',        KS_TEMPL_STAT_PARAM_REG = new RegExp(KS_TEMPL_STAT_PARAM, "g"),        KS_TEMPL = 'KS_TEMPL',        KS_DATA = 'KS_DATA_',        KS_AS = 'as',        // note : double quote for generated code        PREFIX = '");',        SUFFIX = KS_TEMPL + '.push("',        PARSER_SYNTAX_ERROR = 'KISSY.Template: Syntax Error. ',        PARSER_RENDER_ERROR = 'KISSY.Template: Render Error. ',        PARSER_PREFIX = 'var ' + KS_TEMPL + '=[],' +            KS_TEMPL_STAT_PARAM + '=false;with(',        PARSER_MIDDLE = '||{}){try{' + KS_TEMPL + '.push("',        PARSER_SUFFIX = '");}catch(e){' + KS_TEMPL + '=["' +            PARSER_RENDER_ERROR + '" + e.message]}};return ' +            KS_TEMPL + '.join("");',        // restore double quote in logic template variable        restoreQuote = function(str) {            return str.replace(/\\"/g, '"');        },        // escape double quote in template        escapeQuote = function(str) {            return str.replace(/"/g, '\\"');        },        trim = S.trim,        // build a static parser        buildParser = function(tpl) {            var _parser,                _empty_index;            return escapeQuote(trim(tpl)                .replace(/[\r\t\n]/g, ' ')                // escape escape ... . in case \ is consumed when run tpl parser function                // '{{y}}\\x{{/y}}' =>tmpl.push('\x'); => tmpl.push('\\x');                .replace(/\\/g, '\\\\'))                .replace(/\{\{([#/]?)(?!\}\})([^}]*)\}\}/g,                function(all, expr, body) {                    _parser = "";                    // must restore quote , if str is used as code directly                    body = restoreQuote(trim(body));                    //body = trim(body);                    // is an expression                    if (expr) {                        _empty_index = body.indexOf(' ');                        body = _empty_index === -1 ?                            [ body, '' ] :                            [                                body.substring(0, _empty_index),                                body.substring(_empty_index)                            ];                        var operator = body[0],                            fn,                            args = trim(body[1]),                            opStatement = Statements[operator];                        if (opStatement && tagStartEnd[expr]) {                            // get expression definition function/string                            fn = opStatement[tagStartEnd[expr]];                            _parser = String(S.isFunction(fn) ?                                fn.apply(this, args.split(/\s+/)) :                                fn.replace(KS_TEMPL_STAT_PARAM_REG, args));                        }                    }                    // return array directly                    else {                        _parser = KS_TEMPL +                            '.push(' +                            // prevent variable undefined error when look up in with ,simple variable substitution                            // with({}){alert(x);} => ReferenceError: x is not defined                            'typeof (' + body + ') ==="undefined"?"":' + body +                            ');';                    }                    return PREFIX + _parser + SUFFIX;                });        },        // expression        Statements = {            'if': {                start: 'if(typeof (' + KS_TEMPL_STAT_PARAM + ') !=="undefined" && ' + KS_TEMPL_STAT_PARAM + '){',                end: '}'            },            'else': {                start: '}else{'            },            'elseif': {                start: '}else if(' + KS_TEMPL_STAT_PARAM + '){'            },            // KISSY.each function wrap            'each': {                start: function(obj, as, v, k) {                    var _ks_value = '_ks_value',                        _ks_index = '_ks_index';                    if (as === KS_AS && v) {                        _ks_value = v || _ks_value,                            _ks_index = k || _ks_index;                    }                    return 'KISSY.each(' + obj +                        ', function(' + _ks_value +                        ', ' + _ks_index + '){';                },                end: '});'            },            // comments            '!': {                start: '/*' + KS_TEMPL_STAT_PARAM + '*/'            }        };    /**     * Template     * @param {String} tpl template to be rendered.     * @return {Object} return this for chain.     */    function Template(tpl) {        if (!(templateCache[tpl])) {            var _ks_data = S.guid(KS_DATA),                func,                o,                _parser = [                    PARSER_PREFIX,                    _ks_data,                    PARSER_MIDDLE,                    o = buildParser(tpl),                    PARSER_SUFFIX                ];            try {                func = new Function(_ks_data, _parser.join(""));            } catch (e) {                _parser[3] = PREFIX + SUFFIX +                    PARSER_SYNTAX_ERROR + ',' +                    e.message + PREFIX + SUFFIX;                func = new Function(_ks_data, _parser.join(""));            }            templateCache[tpl] = {                name: _ks_data,                o:o,                parser: _parser.join(""),                render: func            };        }        return templateCache[tpl];    }    S.mix(Template, {        /**         * Logging Compiled Template Codes         * @param {String} tpl template string.         */        log: function(tpl) {            if (tpl in templateCache) {                if ('js_beautify' in window) {//                        S.log(js_beautify(templateCache[tpl].parser, {//                            indent_size: 4,//                            indent_char: ' ',//                            preserve_newlines: true,//                            braces_on_own_line: false,//                            keep_array_indentation: false,//                            space_after_anon_function: true//                        }), 'info');                } else {                    S.log(templateCache[tpl].parser, 'info');                }            } else {                Template(tpl);                this.log(tpl);            }        },        /**         * add statement for extending template tags         * @param {String} statement tag name.         * @param {String} o extent tag object.         */        addStatement: function(statement, o) {            if (S.isString(statement)) {                Statements[statement] = o;            } else {                S.mix(Statements, statement);            }        }    });    return Template;});/** * 2011-09-20 note by yiminghe : *      - code style change *      - remove reg cache , ugly to see *      - fix escape by escape *      - expect(T('{{#if a=="a"}}{{b}}\\"{{/if}}').render({a:"a",b:"b"})).toBe('b\\"'); *//** * @fileoverview KISSY.Template Node. * @author 文河<wenhe@taobao.com> */KISSY.add('template/node', function(S, Template, Node) {    var $ = Node.all;    S.mix(S, {        tmpl: function(selector, data) {            return $(Template($(selector).html()).render(data));        }    });}, {requires:["./base",'node']});KISSY.add("template", function(S, T) {    S.Template = T;    return T;}, {    requires:["template/base","template/node"]});
 |