/* Code from v2.2.3, riot master branch (sep 18, 2015) */ var riot = { settings: {} } if (typeof window === 'undefined') window = false var brackets = (function(orig) { var cachedBrackets, r, b, re = /[{}]/g return function(x) { // make sure we use the current setting var s = riot.settings.brackets || orig // recreate cached vars if needed if (cachedBrackets !== s) { cachedBrackets = s b = s.split(' ') r = b.map(function (e) { return e.replace(/(?=.)/g, '\\') }) } // if regexp given, rewrite it with current brackets (only if differ from default) return x instanceof RegExp ? ( s === orig ? x : new RegExp(x.source.replace(re, function(b) { return r[~~(b === '}')] }), x.global ? 'g' : '') ) : // else, get specific bracket b[x] } })('{ }') var tmpl = (function() { var cache = {}, OGLOB = '"in d?d:' + (window ? 'window).' : 'global).'), reVars = /(['"\/])(?:[^\\]*?|\\.|.)*?\1|\.\w*|\w*:|\b(?:(?:new|typeof|in|instanceof) |(?:this|true|false|null|undefined)\b|function\s*\()|([A-Za-z_$]\w*)/g // build a template (or get it from cache), render with data return function(str, data) { return str && (cache[str] || (cache[str] = tmpl(str)))(data) } // create a template instance function tmpl(s, p) { if (s.indexOf(brackets(0)) < 0) { // return raw text s = s.replace(/\n|\r\n?/g, '\n') return function () { return s } } // temporarily convert \{ and \} to a non-character s = s .replace(brackets(/\\{/g), '\uFFF0') .replace(brackets(/\\}/g), '\uFFF1') // split string to expression and non-expresion parts p = split(s, extract(s, brackets(/{/), brackets(/}/))) // is it a single expression or a template? i.e. {x} or {x} s = (p.length === 2 && !p[0]) ? // if expression, evaluate it expr(p[1]) : // if template, evaluate all expressions in it '[' + p.map(function(s, i) { // is it an expression or a string (every second part is an expression) return i % 2 ? // evaluate the expressions expr(s, true) : // process string parts of the template: '"' + s // preserve new lines .replace(/\n|\r\n?/g, '\\n') // escape quotes .replace(/"/g, '\\"') + '"' }).join(',') + '].join("")' return new Function('d', 'return ' + s // bring escaped { and } back .replace(/\uFFF0/g, brackets(0)) .replace(/\uFFF1/g, brackets(1)) + ';') } // parse { ... } expression function expr(s, n) { s = s // convert new lines to spaces .replace(/\n|\r\n?/g, ' ') // trim whitespace, brackets, strip comments .replace(brackets(/^[{ ]+|[ }]+$|\/\*.+?\*\//g), '') // is it an object literal? i.e. { key : value } return /^\s*[\w- "']+ *:/.test(s) ? // if object literal, return trueish keys // e.g.: { show: isOpen(), done: item.done } -> "show done" '[' + // extract key:val pairs, ignoring any nested objects extract(s, // name part: name:, "name":, 'name':, name : /["' ]*[\w- ]+["' ]*:/, // expression part: everything upto a comma followed by a name (see above) or end of line /,(?=["' ]*[\w- ]+["' ]*:)|}|$/ ).map(function(pair) { // get key, val parts return pair.replace(/^[ "']*(.+?)[ "']*: *(.+?),? *$/, function(_, k, v) { // wrap all conditional parts to ignore errors return v.replace(/[^&|=!><]+/g, wrap) + '?"' + k + '":"",' }) }).join('') + '].join(" ").trim()' : // if js expression, evaluate as javascript wrap(s, n) } // execute js w/o breaking on errors or undefined vars function wrap(s, nonull) { s = s.trim() return !s ? '' : '(function(v){try{v=' + // prefix vars (name => data.name) s.replace(reVars, function(s, _, v) { return v ? '(("' + v + OGLOB + v + ')' : s }) + // default to empty string for falsy values except zero '}catch(e){}return ' + (nonull === true ? '!v&&v!==0?"":v' : 'v') + '}).call(d)' } // split string by an array of substrings function split(str, substrings) { var parts = [] substrings.map(function(sub, i) { // push matched expression and part before it i = str.indexOf(sub) parts.push(str.slice(0, i), sub) str = str.slice(i + sub.length) }) if (str) parts.push(str) // push the remaining part return parts } // match strings between opening and closing regexp, skipping any inner/nested matches function extract(str, open, close) { var start, level = 0, matches = [], re = new RegExp('(' + open.source + ')|(' + close.source + ')', 'g') str.replace(re, function(_, open, close, pos) { // if outer inner bracket, mark position if (!level && open) start = pos // in(de)crease bracket level level += open ? 1 : -1 // if outer closing bracket, grab the match if (!level && close != null) matches.push(str.slice(start, pos + close.length)) }) return matches } })() module.exports = { brackets: brackets, tmpl: tmpl }