dist/tmpl.js
/* riot-tmpl v3.0.8, @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
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 _create (str) {
var expr = _getTmpl(str)
if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + 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) {
expr = 'function(v){' + (tb
? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
) + ';return v||v===0?v:""}.call(this)'
}
return expr
}
return _tmpl
})()
tmpl.version = brackets.version = 'v3.0.8'
/* 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)