123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /*
- Copyright 2012, KISSY UI Library v1.20
- MIT Licensed
- build 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"]
- });
|