/* riot-tmpl v1.0.0, @license MIT, (c) 2015 Muut Inc. + contributors */ ;(function (window) { // eslint-disable-line no-extra-semi 'use strict' var skipRegex = (function () { //eslint-disable-line no-unused-vars var beforeReChars = '[{(,;:?=|&!^~>%*/' var beforeReWords = [ 'case', 'default', 'do', 'else', 'in', 'instanceof', 'prefix', 'return', 'typeof', 'void', 'yield' ] var wordsLastChar = beforeReWords.reduce(function (s, w) { return s + w.slice(-1) }, '') var RE_REGEX = /^\/(?=[^*>/])[^[/\\]*(?:(?:\\.|\[(?:\\.|[^\]\\]*)*\])[^[\\/]*)*?\/[gimuy]*/ var RE_VN_CHAR = /[$\w]/ function prev (code, pos) { while (--pos >= 0 && /\s/.test(code[pos])); return pos } function _skipRegex (code, start) { var re = /.*/g var pos = re.lastIndex = start++ var match = re.exec(code)[0].match(RE_REGEX) if (match) { var next = pos + match[0].length pos = prev(code, pos) var c = code[pos] if (pos < 0 || ~beforeReChars.indexOf(c)) { return next } if (c === '.') { if (code[pos - 1] === '.') { start = next } } else if (c === '+' || c === '-') { if (code[--pos] !== c || (pos = prev(code, pos)) < 0 || !RE_VN_CHAR.test(code[pos])) { start = next } } else if (~wordsLastChar.indexOf(c)) { var end = pos + 1 while (--pos >= 0 && RE_VN_CHAR.test(code[pos])); if (~beforeReWords.indexOf(code.slice(pos + 1, end))) { start = next } } } return start } return _skipRegex })() /** * riot.util.brackets * * - `brackets ` - Returns a string or regex based on its parameter * - `brackets.set` - Change the current riot brackets * * @module */ var brackets = (function (UNDEF) { var REGLOB = 'g', R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g, R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|`[^`\\]*(?:\\[\S\s][^`\\]*)*`/g, S_QBLOCKS = R_STRINGS.source + '|' + /(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' + /\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?([^<]\/)[gim]*/.source, UNSUPPORTED = RegExp('[\\' + 'x00-\\x1F<>a-zA-Z0-9\'",;\\\\]'), NEED_ESCAPE = /(?=[[\]()*+?.^$|])/g, S_QBLOCK2 = R_STRINGS.source + '|' + /(\/)(?![*\/])/.source, FINDBRACES = { '(': RegExp('([()])|' + S_QBLOCK2, REGLOB), '[': RegExp('([[\\]])|' + S_QBLOCK2, REGLOB), '{': RegExp('([{}])|' + S_QBLOCK2, REGLOB) }, DEFAULT = '{ }' var _pairs = [ '{', '}', '{', '}', /{[^}]*}/, /\\([{}])/g, /\\({)|{/g, RegExp('\\\\(})|([[({])|(})|' + S_QBLOCK2, REGLOB), DEFAULT, /^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/, /(^|[^\\]){=[\S\s]*?}/ ] var cachedBrackets = UNDEF, _regex, _cache = [], _settings function _loopback (re) { return re } function _rewrite (re, bp) { if (!bp) bp = _cache return new RegExp( re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : '' ) } function _create (pair) { if (pair === DEFAULT) return _pairs var arr = pair.split(' ') if (arr.length !== 2 || UNSUPPORTED.test(pair)) { throw new Error('Unsupported brackets "' + pair + '"') } arr = arr.concat(pair.replace(NEED_ESCAPE, '\\').split(' ')) arr[4] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[4], arr) arr[5] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[5], arr) arr[6] = _rewrite(_pairs[6], arr) arr[7] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCK2, REGLOB) arr[8] = pair return arr } function _brackets (reOrIdx) { return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx] } _brackets.split = function split (str, tmpl, _bp) { // istanbul ignore next: _bp is for the compiler if (!_bp) _bp = _cache var parts = [], match, isexpr, start, pos, re = _bp[6] var qblocks = [] var prevStr = '' var mark, lastIndex isexpr = start = re.lastIndex = 0 while ((match = re.exec(str))) { lastIndex = re.lastIndex pos = match.index if (isexpr) { if (match[2]) { var ch = match[2] var rech = FINDBRACES[ch] var ix = 1 rech.lastIndex = lastIndex while ((match = rech.exec(str))) { if (match[1]) { if (match[1] === ch) ++ix else if (!--ix) break } else { rech.lastIndex = pushQBlock(match.index, rech.lastIndex, match[2]) } } re.lastIndex = ix ? str.length : rech.lastIndex continue } if (!match[3]) { re.lastIndex = pushQBlock(pos, lastIndex, match[4]) continue } } if (!match[1]) { unescapeStr(str.slice(start, pos)) start = re.lastIndex re = _bp[6 + (isexpr ^= 1)] re.lastIndex = start } } if (str && start < str.length) { unescapeStr(str.slice(start)) } parts.qblocks = qblocks return parts function unescapeStr (s) { if (prevStr) { s = prevStr + s prevStr = '' } if (tmpl || isexpr) { parts.push(s && s.replace(_bp[5], '$1')) } else { parts.push(s) } } function pushQBlock(_pos, _lastIndex, slash) { //eslint-disable-line if (slash) { _lastIndex = skipRegex(str, _pos) } if (tmpl && _lastIndex > _pos + 2) { mark = '\u2057' + qblocks.length + '~' qblocks.push(str.slice(_pos, _lastIndex)) prevStr += str.slice(start, _pos) + mark start = _lastIndex } return _lastIndex } } _brackets.hasExpr = function hasExpr (str) { return _cache[4].test(str) } _brackets.loopKeys = function loopKeys (expr) { var m = expr.match(_cache[9]) return m ? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] } : { val: expr.trim() } } _brackets.array = function array (pair) { return pair ? _create(pair) : _cache } function _reset (pair) { if ((pair || (pair = DEFAULT)) !== _cache[8]) { _cache = _create(pair) _regex = pair === DEFAULT ? _loopback : _rewrite _cache[9] = _regex(_pairs[9]) } cachedBrackets = pair } function _setSettings (o) { var b o = o || {} b = o.brackets Object.defineProperty(o, 'brackets', { set: _reset, get: function () { return cachedBrackets }, enumerable: true }) _settings = o _reset(b) } Object.defineProperty(_brackets, 'settings', { set: _setSettings, get: function () { return _settings } }) /* istanbul ignore next: in the browser riot is always in the scope */ _brackets.settings = typeof riot !== 'undefined' && riot.settings || {} _brackets.set = _reset _brackets.skipRegex = skipRegex _brackets.R_STRINGS = R_STRINGS _brackets.R_MLCOMMS = R_MLCOMMS _brackets.S_QBLOCKS = S_QBLOCKS _brackets.S_QBLOCK2 = S_QBLOCK2 return _brackets })() /** * @module tmpl * * tmpl - Root function, returns the template value, render with data * tmpl.hasExpr - Test the existence of a expression inside a string * tmpl.loopKeys - Get the keys for an 'each' loop (used by `_each`) */ var tmpl = (function () { var _cache = {} function _tmpl (str, data) { if (!str) return str return (_cache[str] || (_cache[str] = _create(str))).call( data, _logErr.bind({ data: data, tmpl: str }) ) } _tmpl.hasExpr = brackets.hasExpr _tmpl.loopKeys = brackets.loopKeys // istanbul ignore next _tmpl.clearCache = function () { _cache = {} } _tmpl.errorHandler = null _tmpl.getStr = _getStr; function _logErr (err, ctx) { err.riotData = { tagName: ctx && ctx.__ && ctx.__.tagName, _riot_id: ctx && ctx._riot_id //eslint-disable-line camelcase } if (_tmpl.errorHandler) _tmpl.errorHandler(err) else if ( typeof console !== 'undefined' && typeof console.error === 'function' ) { console.error(err.message) console.log('<%s> %s', err.riotData.tagName || 'Unknown tag', this.tmpl) // eslint-disable-line console.log(this.data) // eslint-disable-line } } function _getStr(str) { var expr = _getTmpl(str) if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr expr = 'var ' + (typeof window !== 'object' ? 'global' : 'window') + ' = {}; ' + expr return expr; } function _create (str) { var expr = _getTmpl(str) if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr expr = 'var ' + (typeof window !== 'object' ? 'global' : 'window') + ' = {}; ' + expr return new Function('E', expr + ';') // eslint-disable-line no-new-func } var RE_DQUOTE = /\u2057/g var RE_QBMARK = /\u2057(\d+)~/g function _getTmpl (str) { var parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1) var qstr = parts.qblocks var expr if (parts.length > 2 || parts[0]) { var i, j, list = [] for (i = j = 0; i < parts.length; ++i) { expr = parts[i] if (expr && (expr = i & 1 ? _parseExpr(expr, 1, qstr) : '"' + expr .replace(/\\/g, '\\\\') .replace(/\r\n?|\n/g, '\\n') .replace(/"/g, '\\"') + '"' )) list[j++] = expr } expr = j < 2 ? list[0] : '[' + list.join(',') + '].join("")' } else { expr = _parseExpr(parts[1], 0, qstr) } if (qstr.length) { expr = expr.replace(RE_QBMARK, function (_, pos) { return qstr[pos] .replace(/\r/g, '\\r') .replace(/\n/g, '\\n') }) } return expr } var RE_CSNAME = /^(?:(-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*)|\u2057(\d+)~):/ var RE_BREND = { '(': /[()]/g, '[': /[[\]]/g, '{': /[{}]/g } function _parseExpr (expr, asText, qstr) { expr = expr .replace(/\s+/g, ' ').trim() .replace(/\ ?([[\({},?\.:])\ ?/g, '$1') if (expr) { var list = [], cnt = 0, match while (expr && (match = expr.match(RE_CSNAME)) && !match.index ) { var key, jsb, re = /,|([[{(])|$/g expr = RegExp.rightContext key = match[2] ? qstr[match[2]].slice(1, -1).trim().replace(/\s+/g, ' ') : match[1] while (jsb = (match = re.exec(expr))[1]) skipBraces(jsb, re) jsb = expr.slice(0, match.index) expr = RegExp.rightContext list[cnt++] = _wrapExpr(jsb, 1, key) } expr = !cnt ? _wrapExpr(expr, asText) : cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0] } return expr function skipBraces (ch, re) { var mm, lv = 1, ir = RE_BREND[ch] ir.lastIndex = re.lastIndex while (mm = ir.exec(expr)) { if (mm[0] === ch) ++lv else if (!--lv) break } re.lastIndex = lv ? expr.length : ir.lastIndex } } // istanbul ignore next: not both var // eslint-disable-next-line max-len JS_CONTEXT = '"in this?this:' + (typeof window !== 'object' ? 'global' : 'window') + ').', JS_VARNAME = /[,{][\$\w]+(?=:)|(^ *|[^$\w\.{])(?!(?:typeof|true|false|null|undefined|in|instanceof|is(?:Finite|NaN)|void|NaN|new|Date|RegExp|Math)(?![$\w]))([$_A-Za-z][$\w]*)/g, JS_NOPROPS = /^(?=(\.[$\w]+))\1(?:[^.[(]|$)/ function _wrapExpr (expr, asText, key) { var tb expr = expr.replace(JS_VARNAME, function (match, p, mvar, pos, s) { if (mvar) { pos = tb ? 0 : pos + match.length if (mvar !== 'this' && mvar !== 'global' && mvar !== 'window') { match = p + '("' + mvar + JS_CONTEXT + mvar if (pos) tb = (s = s[pos]) === '.' || s === '(' || s === '[' } else if (pos) { tb = !JS_NOPROPS.test(s.slice(pos)) } } return match }) if (tb) { expr = 'try{return ' + expr + '}catch(e){E(e,this)}' } if (key) { expr = (tb ? 'function(){' + expr + '}.call(this)' : '(' + expr + ')' ) + '?"' + key + '":""' } else if (asText) { if (expr === 'false') { expr = 'function(v){' + (tb ? expr.replace('return ', 'v=') : 'v=(' + expr + ')' ) + ';return false}.call(this)' } else { expr = 'function(v){' + (tb ? expr.replace('return ', 'v=') : 'v=(' + expr + ')' ) + ';return v||v===0||v===false?v:""}.call(this)' } } return expr } return _tmpl })() tmpl.version = brackets.version = 'v1.0.0' /* istanbul ignore else */ if (typeof module === 'object' && module.exports) { module.exports = { tmpl: tmpl, brackets: brackets } } else if (typeof define === 'function' && typeof define.amd !== 'undefined') { define(function () { return { tmpl: tmpl, brackets: brackets } }) } else if (window) { window.tmpl = tmpl window.brackets = brackets } })(typeof window === 'object' ? /* istanbul ignore next */ window : void 0)