first commit
This commit is contained in:
22
node_modules/@n8n_io/riot-tmpl/LICENSE
generated
vendored
Normal file
22
node_modules/@n8n_io/riot-tmpl/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Riot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
86
node_modules/@n8n_io/riot-tmpl/README.md
generated
vendored
Normal file
86
node_modules/@n8n_io/riot-tmpl/README.md
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Code Quality][codeclimate-image]][codeclimate-url]
|
||||
[![Coverage Status][coverage-image]][coverage-url]
|
||||
[![NPM version][npm-version-image]][npm-url]
|
||||
[![NPM downloads][npm-dn-image]][npm-url]
|
||||
[![MIT License][license-image]][license-url]
|
||||
|
||||
# Tmpl
|
||||
|
||||
The riot template engine
|
||||
|
||||
## Installation
|
||||
|
||||
### Npm
|
||||
|
||||
```sh
|
||||
npm install @n8n-io/riot-tmpl --save
|
||||
```
|
||||
|
||||
### Bower
|
||||
|
||||
From v2.4.2, bower is not supported.
|
||||
|
||||
## Documentation
|
||||
|
||||
### How it works?
|
||||
|
||||
|
||||
Three ways:
|
||||
|
||||
- Expressions: `tmpl('{ value }', data)`.
|
||||
Returns the result of evaluated expression as a raw object.
|
||||
|
||||
- Templates: `tmpl('Hi { name } { surname }', data)`.
|
||||
Returns a string with evaluated expressions.
|
||||
|
||||
- Filters: `tmpl('{ show: !done, highlight: active }', data)`.
|
||||
Returns a space separated list of trueish keys (mainly used for setting html classes), e.g. "show highlight".
|
||||
|
||||
|
||||
### Template examples
|
||||
|
||||
```js
|
||||
tmpl('{ title || "Untitled" }', data)
|
||||
tmpl('Results are { results ? "ready" : "loading" }', data)
|
||||
tmpl('Today is { new Date() }', data)
|
||||
tmpl('{ message.length > 140 && "Message is too long" }', data)
|
||||
tmpl('This item got { Math.round(rating) } stars', data)
|
||||
tmpl('<h1>{ title }</h1>{ body }', data)
|
||||
```
|
||||
|
||||
|
||||
### Falsy expressions
|
||||
|
||||
In templates (as opposed to single expressions) all falsy values except zero (undefined/null/false) will default to empty string:
|
||||
|
||||
```js
|
||||
tmpl('{ undefined } - { false } - { null } - { 0 }', {})
|
||||
// will return: " - - - 0"
|
||||
|
||||
tmpl('{}') // undefined
|
||||
tmpl('{ false }', {}) // false
|
||||
tmpl('{ null }', {}) // null
|
||||
tmpl('{ 0 }', {}) // 0
|
||||
```
|
||||
|
||||
## Changes in v2.3
|
||||
|
||||
* Brackets can not contain characters in the set `[\x00-\x1F<>a-zA-Z0-9'",;\\]`
|
||||
* No comments in expressions, the compiler is the only that strip comments
|
||||
* Attributes with expressions containing `>` must be quoted
|
||||
|
||||
See [API](doc/API.md) and [CHANGES](doc/CHANGES.md) for details.
|
||||
|
||||
|
||||
[npm-version-image]: https://img.shields.io/npm/v/riot-tmpl.svg?style=flat-square
|
||||
[npm-dn-image]: https://img.shields.io/npm/dm/riot-tmpl.svg?style=flat-square
|
||||
[npm-url]: https://npmjs.org/package/riot-tmpl
|
||||
[license-image]: https://img.shields.io/badge/license-MIT-000000.svg?style=flat-square
|
||||
[license-url]: LICENSE
|
||||
[travis-image]: https://img.shields.io/travis/riot/tmpl.svg?style=flat-square
|
||||
[travis-url]: https://travis-ci.org/riot/tmpl
|
||||
[coverage-image]: https://img.shields.io/coveralls/riot/tmpl/master.svg?style=flat-square
|
||||
[coverage-url]: https://coveralls.io/r/riot/tmpl/?branch=master
|
||||
[codeclimate-image]: https://img.shields.io/codeclimate/github/riot/tmpl.svg?style=flat-square
|
||||
[codeclimate-url]: https://codeclimate.com/github/riot/tmpl
|
||||
7735
node_modules/@n8n_io/riot-tmpl/dist/csp.tmpl.js
generated
vendored
Normal file
7735
node_modules/@n8n_io/riot-tmpl/dist/csp.tmpl.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
558
node_modules/@n8n_io/riot-tmpl/dist/es6.tmpl.js
generated
vendored
Normal file
558
node_modules/@n8n_io/riot-tmpl/dist/es6.tmpl.js
generated
vendored
Normal file
@@ -0,0 +1,558 @@
|
||||
|
||||
/**
|
||||
* The riot template engine
|
||||
* @version v1.0.0
|
||||
*/
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
/* global riot */
|
||||
|
||||
export
|
||||
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`)
|
||||
*/
|
||||
|
||||
export
|
||||
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
|
||||
}
|
||||
|
||||
_tmpl.version = brackets.version = 'v1.0.0'
|
||||
|
||||
return _tmpl
|
||||
|
||||
})()
|
||||
571
node_modules/@n8n_io/riot-tmpl/dist/tmpl.js
generated
vendored
Normal file
571
node_modules/@n8n_io/riot-tmpl/dist/tmpl.js
generated
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
|
||||
/* 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)
|
||||
145
node_modules/@n8n_io/riot-tmpl/doc/API.md
generated
vendored
Normal file
145
node_modules/@n8n_io/riot-tmpl/doc/API.md
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
|
||||
# The riot-tmpl API
|
||||
|
||||
## tmpl
|
||||
|
||||
|
||||
### `tmpl` function
|
||||
|
||||
_usage:_ `tmpl( str, data )`
|
||||
|
||||
The exposed `tmpl` function returns the template value from the cache, render with data.
|
||||
|
||||
_parameters_
|
||||
|
||||
* `str` : string - Expression or template with zero or more expressions
|
||||
* `data` : object - A Tag instance, for setting the context
|
||||
|
||||
_returns:_ string - Raw value of the expression or template to render
|
||||
|
||||
|
||||
### `hasExpr` function
|
||||
|
||||
_usage:_ `brackets.hasExpr( str )`
|
||||
|
||||
Checks for an expression within a string, using the current brackets.
|
||||
|
||||
_parameters_
|
||||
|
||||
* `str` : string - String where to search
|
||||
|
||||
_returns:_ boolean - `true` if the string contains an expression
|
||||
|
||||
NOTE: This function only checks for a pair of unescaped riot brackets, does not validate
|
||||
the expression nor excludes brackets within quotes.
|
||||
|
||||
|
||||
### `errorHandler` property
|
||||
|
||||
_type:_ function
|
||||
|
||||
Defines a custom function to handle evaluation errors.
|
||||
|
||||
The `tmpl.errorHandler` property allows to detect errors _in the evaluation_, by setting its value to a function that receives the generated Error object, augmented with an object `riotData` containing the properties `tagName` and `_riot_id` of the context at error time.
|
||||
|
||||
Other (usually fatal) errors, such as "Parse Error" generated by the Function constructor, are not intercepted.
|
||||
|
||||
If this property is not set, or set to falsy, as in previous versions the error is silently ignored.
|
||||
|
||||
|
||||
## brackets
|
||||
|
||||
Since v2.3, setting the brackets to some characters throws an exception.
|
||||
This is the list of invalid characters:
|
||||
|
||||
- Control characters from `\x00` to `\x1F` that can be changed by browsers or minification tools
|
||||
- Alphanumeric `a-z`, `A-Z`, and `0-9`, wich are confused with JS variable names
|
||||
- Single and double quotes, comma, semicolon and backslash `'`, `"`, `,`, `;`, `\`, for obvious reasons
|
||||
- The dangerous `<` and `>` characters, reserved for use in markup and strictly prohibited in unquoted text for any other purpose -- out of CDATA sections.
|
||||
|
||||
See the [CHANGES](CHANGES.md) document for details.
|
||||
|
||||
|
||||
### `brackets` function
|
||||
|
||||
_Syntax:_ `brackets( reOrIdx ) : RegExp | string`
|
||||
|
||||
The brackets function accepts a RegExp or numeric parameter.
|
||||
|
||||
_parameters_
|
||||
|
||||
* `reOrIdx` : RegExp or number - regex to convert or index number of backets part
|
||||
|
||||
_returns:_ RegExp or string - With a regex, this function returns the original regex if the current brackets are the defaults, or a new one with the default brackets replaced by the current custom brackets.
|
||||
With a numeric parameter, returns a value based on current brackets according to the following table (defaults are within parenthesis):
|
||||
|
||||
* 0: left bracket (`{`)
|
||||
* 1: right bracket (`}`)
|
||||
* 2: left escaped bracket (`{`)*
|
||||
* 3: right escaped bracket (`}`)*
|
||||
* 4: RegExp which matches a brackets pair (`/{[^}]*}/`)\*\*
|
||||
|
||||
\* only the characters in `[]()*+?.^$|` are escaped.
|
||||
|
||||
\*\* not 100% accurate, because it does not recognize brackets within strings.
|
||||
|
||||
|
||||
### `set` function
|
||||
|
||||
_Syntax:_ `brackets.set( brackets_pair )`
|
||||
|
||||
Receives the new string for the brackets pair. If you pass a falsy value, brackets are reset to default.
|
||||
This function checks their parameter and reconfigures the internal state immediately.
|
||||
|
||||
_parameters_
|
||||
|
||||
* `brackets_pair` : string - (optional) new custom brackets pair. The start and end is separated with a space character.
|
||||
|
||||
**NOTE:**
|
||||
From v2.3.15, any change in `riot.settings.brackets` is detected, resulting in a call to `brackets.set` and the reconfiguration is immediate.
|
||||
|
||||
|
||||
### `R_MLCOMMS` property
|
||||
|
||||
_Type:_ RegExp
|
||||
|
||||
Used by internal functions and shared with the riot compiler, matches valid, multiline JavaScript comments in almost all forms. Can handle embedded sequences `/*`, `*\/` and `//` in these. Skips non-valid comments like `/*/`.
|
||||
|
||||
`R_MLCOMMS` does not make captures.
|
||||
|
||||
|
||||
### `R_STRINGS` property
|
||||
|
||||
_Type:_ RegExp
|
||||
|
||||
Used by internal functions and shared with the riot compiler, matches single or double quoted strings, handles embedded quotes and multi-line strings (not in accordance with the JavaScript spec). It is not for ES6 template strings, these are too complex for a regex.
|
||||
|
||||
`R_STRINGS` does not make captures.
|
||||
|
||||
|
||||
### `S_QBLOCK` property
|
||||
|
||||
_Type:_ string
|
||||
|
||||
Combines the `brackets.R_STRINGS` source with regexes for matching division symbols and literal regexes.
|
||||
|
||||
When dealing with clean JavaScript code, i.e. without comments, this is the only string you need to instantiate your RegExp object. For code containing comments, `S_QBLOCK` needs to be combined with other regexes for exclusion of multiline and single-line comments (`MLCOMMS` can be one of both).
|
||||
|
||||
The `S_QBLOCK` part captures in `$1` and `$2` a single slash, depending if it matches a division symbol ($1) or a regex ($2). If there's no matches for any of these, they have empty strings.
|
||||
|
||||
_Example:_
|
||||
|
||||
```js
|
||||
// We can use riot.util.brackets if riot is in context
|
||||
var brackets = require('riot-tmpl').brackets
|
||||
|
||||
// Creates the regex, $1 encloses the whole S_QBLOCK, for easier detection
|
||||
var JS_RMCOMMS = new RegExp(
|
||||
'(' + brackets.S_QBLOCK + ')|' + brackets.R_MLCOMMS.source + '|//[^\r\n]*',
|
||||
'g')
|
||||
|
||||
// Replaces comments with a space (_1 is a string, division sign, or regex)
|
||||
function stripComments(str) {
|
||||
return.replace(JS_RMCOMMS, function (m, _1) { return _1 ? m : ' ' })
|
||||
}
|
||||
```
|
||||
83
node_modules/@n8n_io/riot-tmpl/doc/CHANGES.md
generated
vendored
Normal file
83
node_modules/@n8n_io/riot-tmpl/doc/CHANGES.md
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
# The Changes
|
||||
|
||||
I'll try to explain the reason for the some changes in tmpl 2.3.x
|
||||
|
||||
## Escaped brackets, backslashes, and EOLs
|
||||
|
||||
Escaped brackets _within expressions_ are left unescaped, except in JavaScript strings and regexes, where are preserved. So far, I have not found a case where brackets within expressions must remain escaped.
|
||||
|
||||
In the HTML part, escaped brackets are unescaped before the evaluation.
|
||||
|
||||
EOLs are normalized to `\n` in the HTML and converted to compact spaces in expressions.
|
||||
In JavaScript strings and regexes, escaped characters `\r` and `\n` are preserved.
|
||||
|
||||
## Handling evaluation errors
|
||||
|
||||
The new `tmpl.errorHandler` property allows to detect errors _in the evaluation_, by setting its value to a function that receives the generated Error object, augmented with an object `riotData` containing the properties `tagName` and `_riot_id` of the context at error time.
|
||||
|
||||
Other (usually fatal) errors, such as "Parse Error" generated for the Function constructor, are not intercepted.
|
||||
|
||||
If this property is not set, or set to falsy, as in previous versions the error is silently ignored.
|
||||
|
||||
Example:
|
||||
```html
|
||||
<mytag></mytag>
|
||||
<script type="riot/tag">
|
||||
<mytag><p>{ foo.bar }</p></mytag>
|
||||
</script>
|
||||
<script>
|
||||
riot.util.tmpl.errorHandler = function (err) {
|
||||
console.error(err.message + ' in ' + err.riotData.tagName)
|
||||
}
|
||||
riot.mount('*')
|
||||
</script>
|
||||
```
|
||||
outputs "Cannot read property 'bar' of undefined in MYTAG" in the console.
|
||||
|
||||
Ref: [riot#871](https://github.com/riot/riot/issues/871), [riot#1189](https://github.com/riot/riot/issues/1189)
|
||||
|
||||
## The new brackets function
|
||||
|
||||
brackets 2.3 combines the behavior of brackets 2.2 with a new one, based on a function to make immediate, more secure changes to custom brackets. ~~There is a performance penalty in supporting both schemes, but compatibility is maintained.~~
|
||||
|
||||
If riot is available when `brackets` is instantiated, `brackets` uses the configuration in `riot.settings`. In this way, `brackets` works as in previous versions and the reconfiguration is delayed to the first use.
|
||||
If riot is not available, you can change the brackets through the new `brackets.set` function, which accepts the same parameter as `riot.settings.brackets` and makes the reconfiguration immediately.
|
||||
|
||||
**NOTE:**
|
||||
From v2.3.15, brackets changes in browsers via `riot.settings.brackets` has immediate effect and always reflect the brackets in use, the `brackets.settings` property is not neccesary and will be removed in v2.4.0
|
||||
|
||||
It is all, syntax and behavior are the same as older versions: `brackets(regex_or_number)`.
|
||||
|
||||
## Characters not allowed in brackets
|
||||
|
||||
There are characters not allowed to define brackets, some are common characters in JavaScript expressions that hinder finding the right riot brackets, and other are forbidden by the HTML specs for text elements.
|
||||
|
||||
This is the list of invalid characters:
|
||||
|
||||
- Control characters from `\x00` to `\x1F` that can be changed by browsers or minifier tools
|
||||
- Alphanumeric `a-z`, `A-Z`, and `0-9`, wich are confused with JS variable names
|
||||
- Single and double quotes, comma, semicolon and backslash `'`, `"`, `,`, `;`, `\`, for obvious reasons
|
||||
- The dangerous `<` and `>` characters, reserved for use in markup and strictly prohibited in unquoted text for any other purpose -- out of CDATA sections.
|
||||
|
||||
Typically, by using `<>` the browser will send to riot something different to what the user wants. With preprocessors such as ASP, no problems. But riot is not one of them, even with precompiled tags, it's a postprocessor. See the difference:
|
||||
|
||||
#### ASP
|
||||
|
||||
Source –> | ASP parser –> | Browser
|
||||
-------------------|----------------|-----------
|
||||
`<p><%= x %></p>` | `<p>X</p>` | (Renders "X")
|
||||
|
||||
ASP takes the value of `x`, does the substitution, and stops here. The browser (HTML parser) receives valid HTML.
|
||||
|
||||
#### riot
|
||||
|
||||
Source –> | Browser –> | riot parser –>
|
||||
------------------|----------------------|----------------
|
||||
`<p><%= x %></p>` | Renders `<p><></p>`? | `<p><></p>`
|
||||
|
||||
Here the browser (some version of IE) receives invalid markup and try to render the best it can without break the page (i.e. "fix" the error). riot has no chance to get the expression and re-render the value. Other browser _can_ keep the markup as-is depending on its location in the elements. Anyway, the result is unpredictable.
|
||||
|
||||
## Final Note
|
||||
|
||||
There's more new functions and properties added to `brackets`, you can use [hasExpr](https://github.com/riot/tmpl/blob/dev/doc/API.md#hasexpr-function) and the [regexes](https://github.com/riot/tmpl/blob/dev/doc/API.md#r_mlcomms-property) which will be maintained, but the additional functions are for internal use.
|
||||
20
node_modules/@n8n_io/riot-tmpl/index.d.ts
generated
vendored
Normal file
20
node_modules/@n8n_io/riot-tmpl/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
declare module "@n8n_io/riot-tmpl" {
|
||||
interface BracketSettings {
|
||||
brackets: string;
|
||||
}
|
||||
|
||||
interface Brackets {
|
||||
set(token: string): void;
|
||||
settings: BracketSettings;
|
||||
}
|
||||
|
||||
type ReturnValue = string | null | (() => unknown);
|
||||
interface Tmpl {
|
||||
errorHandler?(error: Error): void;
|
||||
getStr(expr: string): string;
|
||||
(value: string, data: unknown): ReturnValue;
|
||||
}
|
||||
|
||||
let brackets: Brackets;
|
||||
let tmpl: Tmpl;
|
||||
}
|
||||
70
node_modules/@n8n_io/riot-tmpl/package.json
generated
vendored
Normal file
70
node_modules/@n8n_io/riot-tmpl/package.json
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "@n8n_io/riot-tmpl",
|
||||
"version": "4.0.1",
|
||||
"description": "n8n fork of the riot template engine",
|
||||
"main": "dist/tmpl.js",
|
||||
"module": "dist/es6.tmpl.js",
|
||||
"jsnext:main": "dist/es6.tmpl.js",
|
||||
"types": "index.d.ts",
|
||||
"directories": {
|
||||
"doc": "doc"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"doc",
|
||||
"dist/*.js",
|
||||
"test/**",
|
||||
"index.d.ts"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "make test",
|
||||
"prepublish": "make build && ./node_modules/.bin/riot-bump"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/n8n-io/tmpl.git"
|
||||
},
|
||||
"keywords": [
|
||||
"riot",
|
||||
"tmpl",
|
||||
"template",
|
||||
"engine",
|
||||
"n8n"
|
||||
],
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.13.1",
|
||||
"eslint": "^3.19.0",
|
||||
"esprima": "^3.1.3",
|
||||
"expect.js": "^0.3.1",
|
||||
"hoister": "0.0.2",
|
||||
"istanbul": "^0.4.5",
|
||||
"jspreproc": "^0.2.7",
|
||||
"karma": "^1.7.0",
|
||||
"karma-browserstack-launcher": "^1.2.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"mocha": "^3.3.0",
|
||||
"phantomjs-prebuilt": "^2.1.14",
|
||||
"riot-bump": "^1.0.0",
|
||||
"rollup": "^0.41.6",
|
||||
"rollup-plugin-commonjs": "^8.0.2",
|
||||
"rollup-plugin-node-resolve": "^3.0.0"
|
||||
},
|
||||
"author": "Riot maintainers team + smart people from all over the world",
|
||||
"contributors": [
|
||||
"Richard Bondi https://github.com/rsbondi",
|
||||
"Gianluca Guarini https://github.com/GianlucaGuarini",
|
||||
"Tsutomu Kawamura https://github.com/cognitom",
|
||||
"Alberto Martínez https://github.com/aMarCruz",
|
||||
"Tero Piirainen https://github.com/tipiirai"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/n8n-io/tmpl/issues"
|
||||
},
|
||||
"homepage": "https://github.com/n8n-io/tmpl#readme",
|
||||
"dependencies": {
|
||||
"eslint-config-riot": "^1.0.0"
|
||||
}
|
||||
}
|
||||
429
node_modules/@n8n_io/riot-tmpl/src/brackets.js
generated
vendored
Normal file
429
node_modules/@n8n_io/riot-tmpl/src/brackets.js
generated
vendored
Normal file
@@ -0,0 +1,429 @@
|
||||
/**
|
||||
* riot.util.brackets
|
||||
*
|
||||
* - `brackets ` - Returns a string or regex based on its parameter
|
||||
* - `brackets.set` - Change the current riot brackets
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
//#if 0 // only in the unprocessed source
|
||||
/* eslint no-unused-vars: [2, {args: "after-used", varsIgnorePattern: "^brackets$"}] */
|
||||
/* global skipRegex */
|
||||
//#endif
|
||||
|
||||
//#if ES6
|
||||
/* global riot */
|
||||
|
||||
export
|
||||
//#endif
|
||||
var brackets = (function (UNDEF) {
|
||||
//
|
||||
// Closure data
|
||||
// --------------------------------------------------------------------------
|
||||
//
|
||||
//#set $_RIX_TEST = 4
|
||||
//#set $_RIX_ESC = 5
|
||||
//#set $_RIX_OPEN = 6
|
||||
//#set $_RIX_CLOSE = 7
|
||||
//#set $_RIX_PAIR = 8
|
||||
//#set $_RIX_LOOP = 9
|
||||
//#ifndef $_RIX_TEST
|
||||
var
|
||||
$_RIX_TEST = 4, // DONT'T FORGET SYNC THE #set BLOCK!!!
|
||||
$_RIX_ESC = 5,
|
||||
$_RIX_OPEN = 6,
|
||||
$_RIX_CLOSE = 7,
|
||||
$_RIX_PAIR = 8,
|
||||
$_RIX_LOOP = 9
|
||||
//#endif
|
||||
|
||||
var
|
||||
REGLOB = 'g',
|
||||
|
||||
/**
|
||||
* Used by internal functions and shared with the riot compiler, matches valid,
|
||||
* multiline JavaScript comments in almost all its forms. Can handle embedded
|
||||
* sequences `/\*`, `*\/` and `//` inside these. Skips non-valid comments like `/*\/`
|
||||
*
|
||||
* `R_MLCOMMS` does not make captures.
|
||||
* @const {RegExp}
|
||||
* @static
|
||||
*/
|
||||
R_MLCOMMS = /\/\*[^*]*\*+(?:[^*\/][^*]*\*+)*\//g,
|
||||
|
||||
/**
|
||||
* Used by internal functions and shared with the riot compiler, matches single or
|
||||
* double quoted strings, handles embedded quotes and multi-line strings (not in
|
||||
* accordance with the JavaScript spec).
|
||||
* It is not for ES6 template strings.
|
||||
*
|
||||
* `R_STRINGS` does not make captures.
|
||||
* @const {RegExp}
|
||||
* @static
|
||||
*/
|
||||
R_STRINGS = /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|`[^`\\]*(?:\\[\S\s][^`\\]*)*`/g,
|
||||
|
||||
/**
|
||||
* For use with the RegExp constructor. Combines the
|
||||
* {@link module:brackets.R_STRINGS|R_STRINGS} source with sources of regexes matching
|
||||
* division operators and literal regexes.
|
||||
* The resulting regex captures in `$1` and `$2` a single slash, depending
|
||||
* if it matches a division operator ($1) or a literal regex ($2).
|
||||
* @const {string}
|
||||
* @static
|
||||
*/
|
||||
S_QBLOCKS = R_STRINGS.source + '|' +
|
||||
/(?:\breturn\s+|(?:[$\w\)\]]|\+\+|--)\s*(\/)(?![*\/]))/.source + '|' +
|
||||
/\/(?=[^*\/])[^[\/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[\/\\]*)*?([^<]\/)[gim]*/.source,
|
||||
|
||||
/**
|
||||
* Characters not supported by the expression parser.
|
||||
* @const {RegExp}
|
||||
* @static
|
||||
*/
|
||||
UNSUPPORTED = RegExp('[\\' + 'x00-\\x1F<>a-zA-Z0-9\'",;\\\\]'),
|
||||
|
||||
/**
|
||||
* These characters have to be escaped - Note that '{}' is not in this list.
|
||||
* @const {RegExp}
|
||||
* @static
|
||||
*/
|
||||
NEED_ESCAPE = /(?=[[\]()*+?.^$|])/g,
|
||||
|
||||
/*
|
||||
JS/ES6 quoted strings and start of regex (basic ES6 does not supports nested backquotes).
|
||||
*/
|
||||
S_QBLOCK2 = R_STRINGS.source + '|' + /(\/)(?![*\/])/.source,
|
||||
|
||||
/**
|
||||
* Hash of regexes for matching JavaScript brackets out of quoted strings and literal
|
||||
* regexes. Used by {@link module:brackets.split|split}, these are heavy, but their
|
||||
* performance is acceptable.
|
||||
* @const {object}
|
||||
* @private
|
||||
*/
|
||||
FINDBRACES = {
|
||||
'(': RegExp('([()])|' + S_QBLOCK2, REGLOB),
|
||||
'[': RegExp('([[\\]])|' + S_QBLOCK2, REGLOB),
|
||||
'{': RegExp('([{}])|' + S_QBLOCK2, REGLOB)
|
||||
},
|
||||
|
||||
/**
|
||||
* The predefined riot brackets
|
||||
* @const {string}
|
||||
* @default
|
||||
*/
|
||||
DEFAULT = '{ }'
|
||||
|
||||
// pre-made string and regexes for the default brackets
|
||||
var _pairs = [
|
||||
'{', '}', // [0-1]: separated brackets
|
||||
'{', '}', // [2-3]: separated brackets (escaped)
|
||||
/{[^}]*}/, // $_RIX_TEST
|
||||
/\\([{}])/g, // $_RIX_ESC
|
||||
/\\({)|{/g, // $_RIX_OPEN
|
||||
RegExp('\\\\(})|([[({])|(})|' + S_QBLOCK2, REGLOB), // $_RIX_CLOSE
|
||||
DEFAULT, // $_RIX_PAIR
|
||||
/^\s*{\^?\s*([$\w]+)(?:\s*,\s*(\S+))?\s+in\s+(\S.*)\s*}/, // $_RIX_LOOP
|
||||
/(^|[^\\]){=[\S\s]*?}/ // $_RIX_RAW
|
||||
]
|
||||
|
||||
// Variable information about the current brackets state, initialized on first use
|
||||
// and on bracket changes.
|
||||
var
|
||||
cachedBrackets = UNDEF, // full brackets string in use, for change detection
|
||||
_regex, // function for regex convertion of default brackets
|
||||
_cache = [], // pre-made string and regexes for the current brackets
|
||||
_settings // mirror `riot.settings`
|
||||
|
||||
//
|
||||
// Private functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Rewrite function for default brackets, returns the received regex as-is.
|
||||
* Used by the main brackets function when the current brackets are the default.
|
||||
* @param {RegExp} re RegExp instance with the default riot brackets
|
||||
* @returns {RegExp} The received regex.
|
||||
* @private
|
||||
*/
|
||||
function _loopback (re) { return re }
|
||||
|
||||
/**
|
||||
* Rewrite the regex with the default brackets replaced with the custom ones.
|
||||
* Used by the main brackets function when the current brackets are not the default.
|
||||
* @param {RegExp} re - RegExp instance with the default riot brackets
|
||||
* @param {Array} [bp] - Escaped brackets in elements 2-3, defaults to those in _cache
|
||||
* @returns {RegExp} Copy of the received regex, with the default brackets replaced.
|
||||
* @private
|
||||
*/
|
||||
function _rewrite (re, bp) {
|
||||
if (!bp) bp = _cache
|
||||
return new RegExp(
|
||||
re.source.replace(/{/g, bp[2]).replace(/}/g, bp[3]), re.global ? REGLOB : ''
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array with pre-made strings and regexes based on the received brackets.
|
||||
* With the default brackets, returns a reference to an inner static array.
|
||||
*
|
||||
* Does not accept `<, >, a-z, A-Z, 0-9` nor control characters.
|
||||
* @param {string} pair - String with the desired brackets pair (cannot be falsy)
|
||||
* @returns {Array} Array with information for the given brackets.
|
||||
* @throws Will throw an "Unsupported brackets ..." if _pair_ is not separated with
|
||||
* exactly one space, or contains an invalid character.
|
||||
* @private
|
||||
*/
|
||||
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[$_RIX_TEST] = _rewrite(arr[1].length > 1 ? /{[\S\s]*?}/ : _pairs[$_RIX_TEST], arr)
|
||||
arr[$_RIX_ESC] = _rewrite(pair.length > 3 ? /\\({|})/g : _pairs[$_RIX_ESC], arr)
|
||||
arr[$_RIX_OPEN] = _rewrite(_pairs[$_RIX_OPEN], arr) // for _split()
|
||||
arr[$_RIX_CLOSE] = RegExp('\\\\(' + arr[3] + ')|([[({])|(' + arr[3] + ')|' + S_QBLOCK2, REGLOB)
|
||||
arr[$_RIX_PAIR] = pair
|
||||
return arr
|
||||
}
|
||||
|
||||
//
|
||||
// "Exported" functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The main function.
|
||||
*
|
||||
* With a numeric parameter, returns the current left (0) or right (1) riot brackets.
|
||||
*
|
||||
* With a regex, returns the original regex if the current brackets are the defaults,
|
||||
* or a new one with the default brackets replaced by the current custom brackets.
|
||||
* @param {RegExp|number} reOrIdx - As noted above
|
||||
* @returns {RegExp|string} Based on the received parameter.
|
||||
* @alias brackets
|
||||
*/
|
||||
function _brackets (reOrIdx) {
|
||||
return reOrIdx instanceof RegExp ? _regex(reOrIdx) : _cache[reOrIdx]
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the received string in its template text and expression parts using
|
||||
* balanced brackets detection to avoid require escaped brackets from users.
|
||||
*
|
||||
* _For internal use by tmpl and the riot-compiler._
|
||||
* @param {string} str - Template source to split, can be one expression
|
||||
* @param {number} [tmpl] - 1 if called from `tmpl()`
|
||||
* @param {Array} [_bp] - Info of custom brackets to use
|
||||
* @returns {Array} - Array containing template text and expressions.
|
||||
* If str was one unique expression, returns two elements: ["", expression].
|
||||
* @private
|
||||
*/
|
||||
_brackets.split = function split (str, tmpl, _bp) {
|
||||
// istanbul ignore next: _bp is for the compiler
|
||||
if (!_bp) _bp = _cache
|
||||
|
||||
// Template text is easy: closing brackets are ignored, all we have to do is find
|
||||
// the first unescaped bracket. The real work is with the expressions...
|
||||
//
|
||||
// Expressions are not so easy. We can already ignore opening brackets, but finding
|
||||
// the correct closing bracket is tricky.
|
||||
// Strings and regexes can contain almost any combination of characters and we
|
||||
// can't deal with these complexity with our regexes, so let's hide and ignore
|
||||
// these. From there, all we need is to detect the bracketed parts and skip
|
||||
// them, as they contains most of the common characters used by riot brackets.
|
||||
// With that, we have a 90% reliability in the detection, although (hope few) some
|
||||
// custom brackets still requires to be escaped.
|
||||
var
|
||||
parts = [], // holds the resulting parts
|
||||
match, // reused by both outer and nested searches
|
||||
isexpr, // we are in ttext (0) or expression (1)
|
||||
start, // start position of current template or expression
|
||||
pos, // current position (exec() result)
|
||||
re = _bp[$_RIX_OPEN] // start with *updated* opening bracket
|
||||
|
||||
var qblocks = [] // quoted strings and regexes
|
||||
var prevStr = ''
|
||||
var mark, lastIndex
|
||||
|
||||
isexpr = start = re.lastIndex = 0 // re is reused, we must reset lastIndex
|
||||
|
||||
while ((match = re.exec(str))) {
|
||||
|
||||
lastIndex = re.lastIndex
|
||||
pos = match.index
|
||||
|
||||
if (isexpr) {
|
||||
// $1: optional escape character,
|
||||
// $2: opening js bracket `{[(`,
|
||||
// $3: closing riot bracket,
|
||||
// $4: opening slashes of regex
|
||||
|
||||
if (match[2]) { // if have a javascript opening bracket,
|
||||
//re.lastIndex = skipBraces(str, match[2], re.lastIndex)
|
||||
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 // skip the bracketed block and loop
|
||||
}
|
||||
|
||||
if (!match[3]) { // if don't have a closing bracket
|
||||
re.lastIndex = pushQBlock(pos, lastIndex, match[4])
|
||||
continue // search again
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, we expect an _unescaped_ openning bracket in $2 for text,
|
||||
// or a closing bracket in $3 for expression.
|
||||
|
||||
if (!match[1]) { // ignore it if have an escape char
|
||||
unescapeStr(str.slice(start, pos)) // push part, even if empty
|
||||
start = re.lastIndex // next position is the new start
|
||||
re = _bp[$_RIX_OPEN + (isexpr ^= 1)] // switch mode and swap regexp
|
||||
re.lastIndex = start // update the regex pointer
|
||||
}
|
||||
}
|
||||
|
||||
if (str && start < str.length) { // push remaining part, if we have one
|
||||
unescapeStr(str.slice(start))
|
||||
}
|
||||
|
||||
// send the literal strings as an array property
|
||||
parts.qblocks = qblocks
|
||||
|
||||
return parts
|
||||
|
||||
// Inner Helpers for _split() -----
|
||||
|
||||
// Store the string in the array `parts`.
|
||||
// Unescape escaped brackets from expressions and, if we are called from
|
||||
// tmpl, from the HTML part too.
|
||||
function unescapeStr (s) {
|
||||
if (prevStr) {
|
||||
s = prevStr + s
|
||||
prevStr = ''
|
||||
}
|
||||
if (tmpl || isexpr) {
|
||||
parts.push(s && s.replace(_bp[$_RIX_ESC], '$1'))
|
||||
} else {
|
||||
parts.push(s)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the js closing bracket for the current block.
|
||||
// Skips strings, regexes, and other inner blocks.
|
||||
function pushQBlock(_pos, _lastIndex, slash) { //eslint-disable-line
|
||||
if (slash) {
|
||||
_lastIndex = skipRegex(str, _pos)
|
||||
}
|
||||
// do not save empty strings or non-regex slashes
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// exposed by riot.util.tmpl.hasExpr
|
||||
_brackets.hasExpr = function hasExpr (str) {
|
||||
return _cache[$_RIX_TEST].test(str)
|
||||
}
|
||||
|
||||
// exposed by riot.util.tmpl.loopKeys
|
||||
_brackets.loopKeys = function loopKeys (expr) {
|
||||
var m = expr.match(_cache[$_RIX_LOOP])
|
||||
|
||||
return m
|
||||
? { key: m[1], pos: m[2], val: _cache[0] + m[3].trim() + _cache[1] }
|
||||
: { val: expr.trim() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with brackets information, defaults to the current brackets.
|
||||
* (the `brackets` module in the node version of the compiler allways defaults
|
||||
* to the predefined riot brackets `{ }`).
|
||||
*
|
||||
* _This function is for internal use._
|
||||
* @param {string} [pair] - If used, returns info for this brackets
|
||||
* @returns {Array} Brackets array in internal format.
|
||||
* @private
|
||||
*/
|
||||
_brackets.array = function array (pair) {
|
||||
return pair ? _create(pair) : _cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the _cache array with strings and regexes based on its parameter.
|
||||
* @param {string} [pair=DEFAULT] - String with the brackets pair to set
|
||||
* @alias brackets.set
|
||||
*/
|
||||
function _reset (pair) {
|
||||
if ((pair || (pair = DEFAULT)) !== _cache[$_RIX_PAIR]) {
|
||||
_cache = _create(pair)
|
||||
_regex = pair === DEFAULT ? _loopback : _rewrite
|
||||
_cache[$_RIX_LOOP] = _regex(_pairs[$_RIX_LOOP])
|
||||
}
|
||||
cachedBrackets = pair // always set these
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows change detection of `riot.settings.brackets`.
|
||||
* @param {object} o - Where store the `brackets` property, mostly `riot.settings`
|
||||
* @private
|
||||
*/
|
||||
function _setSettings (o) {
|
||||
var b
|
||||
|
||||
o = o || {}
|
||||
b = o.brackets
|
||||
Object.defineProperty(o, 'brackets', {
|
||||
set: _reset,
|
||||
get: function () { return cachedBrackets },
|
||||
enumerable: true
|
||||
})
|
||||
_settings = o // save the new reference
|
||||
_reset(b) // update the brackets
|
||||
}
|
||||
|
||||
// Inmediate execution
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Set the internal _settings property as reference to `riot.settings`
|
||||
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
|
||||
|
||||
// Public properties, shared with `tmpl`
|
||||
_brackets.R_STRINGS = R_STRINGS
|
||||
_brackets.R_MLCOMMS = R_MLCOMMS
|
||||
_brackets.S_QBLOCKS = S_QBLOCKS
|
||||
_brackets.S_QBLOCK2 = S_QBLOCK2
|
||||
|
||||
return _brackets
|
||||
|
||||
})()
|
||||
50
node_modules/@n8n_io/riot-tmpl/src/index.js
generated
vendored
Normal file
50
node_modules/@n8n_io/riot-tmpl/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
//#if CSP
|
||||
// note that the path must be relative to the dist/ folder
|
||||
import safeEval from '../src/notevil' //eslint-disable-line no-unused-vars
|
||||
//#endif
|
||||
|
||||
//#if 0
|
||||
/* global tmpl, brackets, window */
|
||||
/* eslint-disable no-void */
|
||||
/* eslint-env amd */
|
||||
//#endif
|
||||
//#if NODE
|
||||
/* riot-tmpl WIP, @license MIT, (c) 2015 Muut Inc. + contributors */
|
||||
;(function (window) { // eslint-disable-line no-extra-semi
|
||||
'use strict'
|
||||
//#else
|
||||
|
||||
/**
|
||||
* The riot template engine
|
||||
* @version WIP
|
||||
*/
|
||||
//#endif
|
||||
|
||||
//#include skip-regex
|
||||
|
||||
//#include brackets
|
||||
|
||||
//#include tmpl
|
||||
|
||||
//#if NODE
|
||||
tmpl.version = brackets.version = 'WIP'
|
||||
|
||||
// support CommonJS, AMD & browser
|
||||
/* 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)
|
||||
//#endif
|
||||
4
node_modules/@n8n_io/riot-tmpl/src/notevil/helpers.js
generated
vendored
Normal file
4
node_modules/@n8n_io/riot-tmpl/src/notevil/helpers.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export function getGlobal (str) {
|
||||
var ctx = (typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this)
|
||||
return typeof str !== 'undefined' ? ctx[str] : ctx
|
||||
}
|
||||
527
node_modules/@n8n_io/riot-tmpl/src/notevil/index.js
generated
vendored
Normal file
527
node_modules/@n8n_io/riot-tmpl/src/notevil/index.js
generated
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
import InfiniteChecker from './lib/infinite-checker'
|
||||
import Primitives from './lib/primitives'
|
||||
import { getGlobal } from './helpers'
|
||||
import esprima from 'esprima'
|
||||
import hoist from 'hoister'
|
||||
|
||||
var maxIterations = 1000000,
|
||||
parse = esprima.parse
|
||||
|
||||
// 'eval' with a controlled environment
|
||||
function safeEval(src, parentContext){
|
||||
var tree = prepareAst(src)
|
||||
var context = Object.create(parentContext || {})
|
||||
return finalValue(evaluateAst(tree, context))
|
||||
}
|
||||
|
||||
safeEval.func = FunctionFactory()
|
||||
|
||||
// create a 'Function' constructor for a controlled environment
|
||||
function FunctionFactory(parentContext){
|
||||
var context = Object.create(parentContext || {})
|
||||
return function Function() {
|
||||
// normalize arguments array
|
||||
var args = Array.prototype.slice.call(arguments)
|
||||
var src = args.slice(-1)[0]
|
||||
args = args.slice(0,-1)
|
||||
if (typeof src === 'string'){
|
||||
//HACK: esprima doesn't like returns outside functions
|
||||
src = parse('function a(){ ' + src + '}').body[0].body
|
||||
}
|
||||
var tree = prepareAst(src)
|
||||
return getFunction(tree, args, context)
|
||||
}
|
||||
}
|
||||
|
||||
// takes an AST or js source and returns an AST
|
||||
function prepareAst(src){
|
||||
var tree = (typeof src === 'string') ? parse(src) : src
|
||||
return hoist(tree)
|
||||
}
|
||||
|
||||
// evaluate an AST in the given context
|
||||
function evaluateAst(tree, context){
|
||||
|
||||
var safeFunction = FunctionFactory(context)
|
||||
var primitives = Primitives(context)
|
||||
|
||||
// block scoped context for catch (ex) and 'let'
|
||||
var blockContext = context
|
||||
|
||||
return walk(tree)
|
||||
|
||||
// recursively walk every node in an array
|
||||
function walkAll(nodes){
|
||||
var result = undefined
|
||||
for (var i=0;i<nodes.length;i++){
|
||||
var childNode = nodes[i]
|
||||
if (childNode.type === 'EmptyStatement') continue
|
||||
result = walk(childNode)
|
||||
if (result instanceof ReturnValue){
|
||||
return result
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// recursively evalutate the node of an AST
|
||||
function walk(node){
|
||||
if (!node) return
|
||||
|
||||
switch (node.type) {
|
||||
|
||||
case 'Program':
|
||||
return walkAll(node.body )
|
||||
|
||||
case 'BlockStatement':
|
||||
enterBlock()
|
||||
var result = walkAll(node.body)
|
||||
leaveBlock()
|
||||
return result
|
||||
|
||||
case 'SequenceExpression':
|
||||
return walkAll(node.expressions)
|
||||
|
||||
case 'FunctionDeclaration':
|
||||
var params = node.params.map(getName)
|
||||
var value = getFunction(node.body, params, blockContext)
|
||||
return context[node.id.name] = value
|
||||
|
||||
case 'FunctionExpression':
|
||||
var params = node.params.map(getName)
|
||||
return getFunction(node.body, params, blockContext)
|
||||
|
||||
case 'ReturnStatement':
|
||||
var value = walk(node.argument)
|
||||
return new ReturnValue('return', value)
|
||||
|
||||
case 'BreakStatement':
|
||||
return new ReturnValue('break')
|
||||
|
||||
case 'ContinueStatement':
|
||||
return new ReturnValue('continue')
|
||||
|
||||
case 'ExpressionStatement':
|
||||
return walk(node.expression)
|
||||
|
||||
case 'AssignmentExpression':
|
||||
return setValue(blockContext, node.left, node.right, node.operator)
|
||||
|
||||
case 'UpdateExpression':
|
||||
return setValue(blockContext, node.argument, null, node.operator)
|
||||
|
||||
case 'VariableDeclaration':
|
||||
node.declarations.forEach(function(declaration){
|
||||
var target = node.kind === 'let' ? blockContext : context
|
||||
if (declaration.init){
|
||||
target[declaration.id.name] = walk(declaration.init)
|
||||
} else {
|
||||
target[declaration.id.name] = undefined
|
||||
}
|
||||
})
|
||||
break
|
||||
|
||||
case 'SwitchStatement':
|
||||
var defaultHandler = null
|
||||
var matched = false
|
||||
var value = walk(node.discriminant)
|
||||
var result = undefined
|
||||
|
||||
enterBlock()
|
||||
|
||||
var i = 0
|
||||
while (result == null){
|
||||
if (i<node.cases.length){
|
||||
if (node.cases[i].test){ // check or fall through
|
||||
matched = matched || (walk(node.cases[i].test) === value)
|
||||
} else if (defaultHandler == null) {
|
||||
defaultHandler = i
|
||||
}
|
||||
if (matched){
|
||||
var r = walkAll(node.cases[i].consequent)
|
||||
if (r instanceof ReturnValue){ // break out
|
||||
if (r.type == 'break') break
|
||||
result = r
|
||||
}
|
||||
}
|
||||
i += 1 // continue
|
||||
} else if (!matched && defaultHandler != null){
|
||||
// go back and do the default handler
|
||||
i = defaultHandler
|
||||
matched = true
|
||||
} else {
|
||||
// nothing we can do
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
leaveBlock()
|
||||
return result
|
||||
|
||||
case 'IfStatement':
|
||||
if (walk(node.test)){
|
||||
return walk(node.consequent)
|
||||
} else if (node.alternate) {
|
||||
return walk(node.alternate)
|
||||
}
|
||||
|
||||
case 'ForStatement':
|
||||
var infinite = InfiniteChecker(maxIterations)
|
||||
var result = undefined
|
||||
|
||||
enterBlock() // allow lets on delarations
|
||||
for (walk(node.init); walk(node.test); walk(node.update)){
|
||||
var r = walk(node.body)
|
||||
|
||||
// handle early return, continue and break
|
||||
if (r instanceof ReturnValue){
|
||||
if (r.type == 'continue') continue
|
||||
if (r.type == 'break') break
|
||||
result = r
|
||||
break
|
||||
}
|
||||
|
||||
infinite.check()
|
||||
}
|
||||
leaveBlock()
|
||||
return result
|
||||
|
||||
case 'ForInStatement':
|
||||
var infinite = InfiniteChecker(maxIterations)
|
||||
var result = undefined
|
||||
|
||||
var value = walk(node.right)
|
||||
var property = node.left
|
||||
|
||||
var target = context
|
||||
enterBlock()
|
||||
|
||||
if (property.type == 'VariableDeclaration'){
|
||||
walk(property)
|
||||
property = property.declarations[0].id
|
||||
if (property.kind === 'let'){
|
||||
target = blockContext
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in value){
|
||||
setValue(target, property, {type: 'Literal', value: key})
|
||||
var r = walk(node.body)
|
||||
|
||||
// handle early return, continue and break
|
||||
if (r instanceof ReturnValue){
|
||||
if (r.type == 'continue') continue
|
||||
if (r.type == 'break') break
|
||||
result = r
|
||||
break
|
||||
}
|
||||
|
||||
infinite.check()
|
||||
}
|
||||
leaveBlock()
|
||||
|
||||
return result
|
||||
|
||||
case 'WhileStatement':
|
||||
var infinite = InfiniteChecker(maxIterations)
|
||||
while (walk(node.test)){
|
||||
walk(node.body)
|
||||
infinite.check()
|
||||
}
|
||||
break
|
||||
|
||||
case 'TryStatement':
|
||||
try {
|
||||
walk(node.block)
|
||||
} catch (error) {
|
||||
enterBlock()
|
||||
var catchClause = node.handlers[0]
|
||||
if (catchClause) {
|
||||
blockContext[catchClause.param.name] = error
|
||||
walk(catchClause.body)
|
||||
}
|
||||
leaveBlock()
|
||||
} finally {
|
||||
if (node.finalizer) {
|
||||
walk(node.finalizer)
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case 'Literal':
|
||||
return node.value
|
||||
|
||||
case 'UnaryExpression':
|
||||
var val = walk(node.argument)
|
||||
switch(node.operator) {
|
||||
case '+': return +val
|
||||
case '-': return -val
|
||||
case '~': return ~val
|
||||
case '!': return !val
|
||||
case 'void': return void val
|
||||
case 'typeof': return typeof val
|
||||
default: return unsupportedExpression(node)
|
||||
}
|
||||
|
||||
case 'ArrayExpression':
|
||||
var obj = blockContext['Array']()
|
||||
for (var i=0;i<node.elements.length;i++){
|
||||
obj.push(walk(node.elements[i]))
|
||||
}
|
||||
return obj
|
||||
|
||||
case 'ObjectExpression':
|
||||
var obj = blockContext['Object']()
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i]
|
||||
var value = (prop.value === null) ? prop.value : walk(prop.value)
|
||||
obj[prop.key.value || prop.key.name] = value
|
||||
}
|
||||
return obj
|
||||
|
||||
case 'NewExpression':
|
||||
var args = node.arguments.map(function(arg){
|
||||
return walk(arg)
|
||||
})
|
||||
var target = walk(node.callee)
|
||||
return primitives.applyNew(target, args)
|
||||
|
||||
|
||||
case 'BinaryExpression':
|
||||
var l = walk(node.left)
|
||||
var r = walk(node.right)
|
||||
|
||||
switch(node.operator) {
|
||||
case '==': return l === r
|
||||
case '===': return l === r
|
||||
case '!=': return l != r
|
||||
case '!==': return l !== r
|
||||
case '+': return l + r
|
||||
case '-': return l - r
|
||||
case '*': return l * r
|
||||
case '/': return l / r
|
||||
case '%': return l % r
|
||||
case '<': return l < r
|
||||
case '<=': return l <= r
|
||||
case '>': return l > r
|
||||
case '>=': return l >= r
|
||||
case '|': return l | r
|
||||
case '&': return l & r
|
||||
case '^': return l ^ r
|
||||
case 'in': return l in r
|
||||
case 'instanceof': return l instanceof r
|
||||
default: return unsupportedExpression(node)
|
||||
}
|
||||
|
||||
case 'LogicalExpression':
|
||||
switch(node.operator) {
|
||||
case '&&': return walk(node.left) && walk(node.right)
|
||||
case '||': return walk(node.left) || walk(node.right)
|
||||
default: return unsupportedExpression(node)
|
||||
}
|
||||
|
||||
case 'ThisExpression':
|
||||
return blockContext['this']
|
||||
|
||||
case 'Identifier':
|
||||
if (node.name === 'undefined'){
|
||||
return undefined
|
||||
} else if (hasProperty(blockContext, node.name, primitives)){
|
||||
return finalValue(blockContext[node.name])
|
||||
} else {
|
||||
throw new ReferenceError(node.name + ' is not defined')
|
||||
}
|
||||
|
||||
case 'CallExpression':
|
||||
|
||||
var args = node.arguments.map(function(arg){
|
||||
return walk(arg)
|
||||
})
|
||||
var object = null
|
||||
var target = walk(node.callee)
|
||||
|
||||
if (node.callee.type === 'MemberExpression'){
|
||||
object = walk(node.callee.object)
|
||||
}
|
||||
return target.apply(object, args)
|
||||
|
||||
case 'MemberExpression':
|
||||
var obj = walk(node.object)
|
||||
if (node.computed){
|
||||
var prop = walk(node.property)
|
||||
} else {
|
||||
var prop = node.property.name
|
||||
}
|
||||
obj = primitives.getPropertyObject(obj, prop)
|
||||
return checkValue(obj[prop]);
|
||||
|
||||
case 'ConditionalExpression':
|
||||
var val = walk(node.test)
|
||||
return val ? walk(node.consequent) : walk(node.alternate)
|
||||
|
||||
case 'EmptyStatement':
|
||||
return
|
||||
|
||||
default:
|
||||
return unsupportedExpression(node)
|
||||
}
|
||||
}
|
||||
|
||||
// safely retrieve a value
|
||||
function checkValue(value){
|
||||
if (value === Function){
|
||||
value = safeFunction
|
||||
}
|
||||
return finalValue(value)
|
||||
}
|
||||
|
||||
// block scope context control
|
||||
function enterBlock(){
|
||||
blockContext = Object.create(blockContext)
|
||||
}
|
||||
function leaveBlock(){
|
||||
blockContext = Object.getPrototypeOf(blockContext)
|
||||
}
|
||||
|
||||
// set a value in the specified context if allowed
|
||||
function setValue(object, left, right, operator){
|
||||
var name = null
|
||||
|
||||
if (left.type === 'Identifier'){
|
||||
name = left.name
|
||||
// handle parent context shadowing
|
||||
object = objectForKey(object, name, primitives)
|
||||
} else if (left.type === 'MemberExpression'){
|
||||
if (left.computed){
|
||||
name = walk(left.property)
|
||||
} else {
|
||||
name = left.property.name
|
||||
}
|
||||
object = walk(left.object)
|
||||
}
|
||||
|
||||
// stop built in properties from being able to be changed
|
||||
if (canSetProperty(object, name, primitives)){
|
||||
switch(operator) {
|
||||
case undefined: return object[name] = walk(right)
|
||||
case '=': return object[name] = walk(right)
|
||||
case '+=': return object[name] += walk(right)
|
||||
case '-=': return object[name] -= walk(right)
|
||||
case '++': return object[name]++
|
||||
case '--': return object[name]--
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// when an unsupported expression is encountered, throw an error
|
||||
function unsupportedExpression(node){
|
||||
console.error(node)
|
||||
var err = new Error('Unsupported expression: ' + node.type)
|
||||
err.node = node
|
||||
throw err
|
||||
}
|
||||
|
||||
// walk a provided object's prototypal hierarchy to retrieve an inherited object
|
||||
function objectForKey(object, key, primitives){
|
||||
var proto = primitives.getPrototypeOf(object)
|
||||
if (!proto || hasOwnProperty(object, key)){
|
||||
return object
|
||||
} else {
|
||||
return objectForKey(proto, key, primitives)
|
||||
}
|
||||
}
|
||||
|
||||
function hasProperty(object, key, primitives){
|
||||
var proto = primitives.getPrototypeOf(object)
|
||||
var hasOwn = hasOwnProperty(object, key)
|
||||
if (object[key] !== undefined){
|
||||
return true
|
||||
} else if (!proto || hasOwn){
|
||||
return hasOwn
|
||||
} else {
|
||||
return hasProperty(proto, key, primitives)
|
||||
}
|
||||
}
|
||||
|
||||
function hasOwnProperty(object, key){
|
||||
return Object.prototype.hasOwnProperty.call(object, key)
|
||||
}
|
||||
|
||||
function propertyIsEnumerable(object, key){
|
||||
return Object.prototype.propertyIsEnumerable.call(object, key)
|
||||
}
|
||||
|
||||
|
||||
// determine if we have write access to a property
|
||||
function canSetProperty(object, property, primitives){
|
||||
if (property === '__proto__' || primitives.isPrimitive(object)){
|
||||
return false
|
||||
} else if (object != null){
|
||||
|
||||
if (hasOwnProperty(object, property)){
|
||||
if (propertyIsEnumerable(object, property)){
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return canSetProperty(primitives.getPrototypeOf(object), property, primitives)
|
||||
}
|
||||
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// generate a function with specified context
|
||||
function getFunction(body, params, parentContext){
|
||||
return function(){
|
||||
var context = Object.create(parentContext),
|
||||
g = getGlobal()
|
||||
|
||||
context['window'] = context['global'] = g
|
||||
|
||||
if (this == g) {
|
||||
context['this'] = null
|
||||
} else {
|
||||
context['this'] = this
|
||||
}
|
||||
// normalize arguments array
|
||||
var args = Array.prototype.slice.call(arguments)
|
||||
context['arguments'] = arguments
|
||||
args.forEach(function(arg,idx){
|
||||
var param = params[idx]
|
||||
if (param){
|
||||
context[param] = arg
|
||||
}
|
||||
})
|
||||
var result = evaluateAst(body, context)
|
||||
|
||||
if (result instanceof ReturnValue){
|
||||
return result.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function finalValue(value){
|
||||
if (value instanceof ReturnValue){
|
||||
return value.value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// get the name of an identifier
|
||||
function getName(identifier){
|
||||
return identifier.name
|
||||
}
|
||||
|
||||
// a ReturnValue struct for differentiating between expression result and return statement
|
||||
function ReturnValue(type, value){
|
||||
this.type = type
|
||||
this.value = value
|
||||
}
|
||||
|
||||
export default safeEval
|
||||
18
node_modules/@n8n_io/riot-tmpl/src/notevil/lib/infinite-checker.js
generated
vendored
Normal file
18
node_modules/@n8n_io/riot-tmpl/src/notevil/lib/infinite-checker.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
function InfiniteChecker (maxIterations) {
|
||||
if (this instanceof InfiniteChecker) {
|
||||
this.maxIterations = maxIterations
|
||||
this.count = 0
|
||||
} else {
|
||||
return new InfiniteChecker(maxIterations)
|
||||
}
|
||||
}
|
||||
|
||||
InfiniteChecker.prototype.check = function () {
|
||||
this.count += 1
|
||||
if (this.count > this.maxIterations) {
|
||||
throw new Error('Infinite loop detected - reached max iterations')
|
||||
}
|
||||
}
|
||||
|
||||
export default InfiniteChecker
|
||||
117
node_modules/@n8n_io/riot-tmpl/src/notevil/lib/primitives.js
generated
vendored
Normal file
117
node_modules/@n8n_io/riot-tmpl/src/notevil/lib/primitives.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import { getGlobal } from '../helpers'
|
||||
|
||||
var names = ['Object', 'String', 'Boolean', 'Number', 'RegExp', 'Date', 'Array']
|
||||
var immutable = { string: 'String', boolean: 'Boolean', number: 'Number' }
|
||||
|
||||
var primitives = names.map(getGlobal)
|
||||
var protos = primitives.map(getProto)
|
||||
|
||||
function Primitives (context) {
|
||||
if (this instanceof Primitives) {
|
||||
this.context = context
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
if (!this.context[names[i]]) {
|
||||
this.context[names[i]] = wrap(primitives[i])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return new Primitives(context)
|
||||
}
|
||||
}
|
||||
|
||||
Primitives.prototype.replace = function (value) {
|
||||
var primIndex = primitives.indexOf(value),
|
||||
protoIndex = protos.indexOf(value),
|
||||
name
|
||||
|
||||
if (~primIndex) {
|
||||
name = names[primIndex]
|
||||
return this.context[name]
|
||||
} else if (~protoIndex) {
|
||||
name = names[protoIndex]
|
||||
return this.context[name].prototype
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
Primitives.prototype.getPropertyObject = function (object, property) {
|
||||
if (immutable[typeof object]) {
|
||||
return this.getPrototypeOf(object)
|
||||
}
|
||||
return object
|
||||
}
|
||||
|
||||
Primitives.prototype.isPrimitive = function (value) {
|
||||
return !!~primitives.indexOf(value) || !!~protos.indexOf(value)
|
||||
}
|
||||
|
||||
Primitives.prototype.getPrototypeOf = function (value) {
|
||||
if (value == null) { // handle null and undefined
|
||||
return value
|
||||
}
|
||||
|
||||
var immutableType = immutable[typeof value],
|
||||
proto
|
||||
|
||||
if (immutableType) {
|
||||
proto = this.context[immutableType].prototype
|
||||
} else {
|
||||
proto = Object.getPrototypeOf(value)
|
||||
}
|
||||
|
||||
if (!proto || proto === Object.prototype) {
|
||||
return null
|
||||
}
|
||||
|
||||
var replacement = this.replace(proto)
|
||||
|
||||
if (replacement === value) {
|
||||
replacement = this.replace(Object.prototype)
|
||||
}
|
||||
return replacement
|
||||
|
||||
}
|
||||
|
||||
Primitives.prototype.applyNew = function (func, args) {
|
||||
if (func.wrapped) {
|
||||
var prim = Object.getPrototypeOf(func)
|
||||
var instance = new (Function.prototype.bind.apply(prim, arguments))
|
||||
|
||||
setProto(instance, func.prototype)
|
||||
return instance
|
||||
}
|
||||
|
||||
return new (Function.prototype.bind.apply(func, arguments))
|
||||
|
||||
}
|
||||
|
||||
function getProto (func) {
|
||||
return func.prototype
|
||||
}
|
||||
|
||||
function setProto (obj, proto) {
|
||||
obj.__proto__ = proto // eslint-disable-line
|
||||
}
|
||||
|
||||
function wrap (prim) {
|
||||
var proto = Object.create(prim.prototype)
|
||||
|
||||
var result = function () {
|
||||
if (this instanceof result) {
|
||||
prim.apply(this, arguments)
|
||||
} else {
|
||||
var instance = prim.apply(null, arguments)
|
||||
|
||||
setProto(instance, proto)
|
||||
return instance
|
||||
}
|
||||
}
|
||||
|
||||
setProto(result, prim)
|
||||
result.prototype = proto
|
||||
result.wrapped = true
|
||||
return result
|
||||
}
|
||||
|
||||
export default Primitives
|
||||
99
node_modules/@n8n_io/riot-tmpl/src/skip-regex.js
generated
vendored
Normal file
99
node_modules/@n8n_io/riot-tmpl/src/skip-regex.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Regex detection.
|
||||
From: https://github.com/riot/parser/blob/master/src/skip-regex.js
|
||||
*/
|
||||
|
||||
var skipRegex = (function () { //eslint-disable-line no-unused-vars
|
||||
|
||||
// safe characters to precced a regex (including `=>`, `**`, and `...`)
|
||||
var beforeReChars = '[{(,;:?=|&!^~>%*/'
|
||||
|
||||
// keyword that can preceed a regex (`in` is handled as special case)
|
||||
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)
|
||||
}, '')
|
||||
|
||||
// The string to test can't include line-endings
|
||||
var RE_REGEX = /^\/(?=[^*>/])[^[/\\]*(?:(?:\\.|\[(?:\\.|[^\]\\]*)*\])[^[\\/]*)*?\/[gimuy]*/
|
||||
var RE_VN_CHAR = /[$\w]/
|
||||
|
||||
// Searches the position of the previous non-blank character inside `code`,
|
||||
// starting with `pos - 1`.
|
||||
function prev (code, pos) {
|
||||
while (--pos >= 0 && /\s/.test(code[pos]));
|
||||
return pos
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the code in the `start` position can be a regex.
|
||||
*
|
||||
* @param {string} code - Buffer to test in
|
||||
* @param {number} start - Position the first slash inside `code`
|
||||
* @returns {number} position of the char following the regex.
|
||||
*/
|
||||
function _skipRegex (code, start) {
|
||||
|
||||
// `exec()` will extract from the slash to the end of line and the
|
||||
// chained `match()` will match the possible regex.
|
||||
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 // result is not from `re.exec`
|
||||
|
||||
pos = prev(code, pos)
|
||||
var c = code[pos]
|
||||
|
||||
// start of buffer or safe prefix?
|
||||
if (pos < 0 || ~beforeReChars.indexOf(c)) {
|
||||
return next
|
||||
}
|
||||
|
||||
// from here, `pos` is >= 0 and `c` is code[pos]
|
||||
// is-tanbul ignore next: This is for ES6
|
||||
if (c === '.') {
|
||||
// can be `...` or something silly like 5./2
|
||||
if (code[pos - 1] === '.') {
|
||||
start = next
|
||||
}
|
||||
|
||||
} else if (c === '+' || c === '-') {
|
||||
// tricky case
|
||||
if (code[--pos] !== c || // if have a single operator or
|
||||
(pos = prev(code, pos)) < 0 || // ...have `++` and no previous token or
|
||||
!RE_VN_CHAR.test(code[pos])) { // ...the token is not a JS var/number
|
||||
start = next // ...this is a regex
|
||||
}
|
||||
|
||||
} else if (~wordsLastChar.indexOf(c)) {
|
||||
// keyword?
|
||||
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
|
||||
|
||||
})()
|
||||
424
node_modules/@n8n_io/riot-tmpl/src/tmpl.js
generated
vendored
Normal file
424
node_modules/@n8n_io/riot-tmpl/src/tmpl.js
generated
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
/**
|
||||
* @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`)
|
||||
*/
|
||||
//#if 0 // only in the unprocessed source
|
||||
/* eslint no-unused-vars: [2, {args: "after-used", varsIgnorePattern: "tmpl"}] */
|
||||
/* global brackets, riot */
|
||||
//#endif
|
||||
//#define LIST_GETTERS 0
|
||||
|
||||
// IIFE for tmpl()
|
||||
//#if ES6
|
||||
export
|
||||
//#endif
|
||||
var tmpl = (function () {
|
||||
//
|
||||
// Closure data
|
||||
// --------------------------------------------------------------------------
|
||||
var _cache = {}
|
||||
|
||||
//
|
||||
// Runtime Functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The exposed tmpl function returns the template value from the cache, render with data.
|
||||
*
|
||||
* @param {string} str - Expression or template with zero or more expressions
|
||||
* @param {Object} data - A Tag instance, for setting the context
|
||||
* @returns {*} Raw value of the expression or template to render
|
||||
* @private
|
||||
*/
|
||||
function _tmpl (str, data) {
|
||||
if (!str) return str // catch falsy values here
|
||||
|
||||
//#if DEBUG
|
||||
/*eslint no-console: 0 */
|
||||
if (data && data._debug_) {
|
||||
data._debug_ = 0
|
||||
if (!_cache[str]) {
|
||||
_cache[str] = _create(str, 1) // request debug output
|
||||
var rs = typeof riot === 'undefined'
|
||||
? '(riot undefined)' : JSON.stringify(riot.settings)
|
||||
|
||||
console.log('--- DEBUG' +
|
||||
'\n riot.settings: ' + rs + '\n data: ' + JSON.stringify(data))
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
|
||||
// At this point, the expressions must have been parsed, it only remains to construct
|
||||
// the function (if it is not in the cache) and call it to replace expressions with
|
||||
// their values. data (`this`) is a Tag instance, _logErr is the error handler.
|
||||
|
||||
return (_cache[str] || (_cache[str] = _create(str))).call(
|
||||
data, _logErr.bind({
|
||||
data: data,
|
||||
tmpl: str
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for an expression within a string, using the current brackets.
|
||||
*
|
||||
* @param {string } str - String where to search
|
||||
* @returns {boolean} `true` if the string contains an expression.
|
||||
* @function
|
||||
*/
|
||||
_tmpl.hasExpr = brackets.hasExpr
|
||||
|
||||
/**
|
||||
* Parses the `each` expression to detect how to map the collection data to the
|
||||
* children tags. Used by riot browser/tag/each.js
|
||||
*
|
||||
* {key, i in items} -> { key, pos, val }
|
||||
*
|
||||
* @param {String} expr - string passed in the 'each' attribute
|
||||
* @returns {Object} The object needed to check how the items in the collection
|
||||
* should be mapped to the children tags.
|
||||
* @function
|
||||
*/
|
||||
_tmpl.loopKeys = brackets.loopKeys
|
||||
|
||||
/**
|
||||
* Clears the internal cache of compiled expressions.
|
||||
*
|
||||
* @function
|
||||
*/
|
||||
// istanbul ignore next
|
||||
_tmpl.clearCache = function () { _cache = {} }
|
||||
|
||||
/**
|
||||
* Holds a custom function to handle evaluation errors.
|
||||
*
|
||||
* This property allows to detect errors _in the evaluation_, by setting its value to a
|
||||
* function that receives the generated Error object, augmented with an object `riotData`
|
||||
* containing the properties `tagName` and `_riot_id` of the context at error time.
|
||||
*
|
||||
* Other (usually fatal) errors, such as "Parse Error" generated by the Function
|
||||
* constructor, are not intercepted.
|
||||
*
|
||||
* If this property is not set, or set to falsy, as in previous versions the error
|
||||
* is silently ignored.
|
||||
*
|
||||
* @type {function}
|
||||
* @static
|
||||
*/
|
||||
_tmpl.errorHandler = null
|
||||
_tmpl.getStr = _getStr;
|
||||
|
||||
/**
|
||||
* Output an error message through the `_tmpl.errorHandler` function and
|
||||
* the console object.
|
||||
* @param {Error} err - The Error instance generated by the exception
|
||||
* @param {object} ctx - The context
|
||||
* @private
|
||||
*/
|
||||
function _logErr (err, ctx) {
|
||||
// add some data to the Error object
|
||||
err.riotData = {
|
||||
tagName: ctx && ctx.__ && ctx.__.tagName,
|
||||
_riot_id: ctx && ctx._riot_id //eslint-disable-line camelcase
|
||||
}
|
||||
|
||||
// user error handler
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function instance to get a value from the received template string.
|
||||
*
|
||||
* It'll halt the app if the expression has errors (Parse Error or SyntaxError).
|
||||
*
|
||||
* @param {string} str - The template. Can include zero or more expressions
|
||||
* @returns {Function} An instance of Function with the compiled template.
|
||||
* @private
|
||||
*/
|
||||
function _create (str) {
|
||||
var expr = _getTmpl(str)
|
||||
|
||||
if (expr.slice(0, 11) !== 'try{return ') expr = 'return ' + expr
|
||||
|
||||
// Create local variable called window to prevent access to global window object
|
||||
expr = 'var ' + (typeof window !== 'object' ? 'global' : 'window') + ' = {}; ' + expr
|
||||
|
||||
//#if DEBUG
|
||||
if (arguments.length > 1) console.log('--- getter:\n `' + expr + '`\n---')
|
||||
//#elif LIST_GETTERS
|
||||
//console.log(' In: `%s`\nOUT: `%s`', str, expr)
|
||||
//#endif
|
||||
/*#if CSP
|
||||
return safeEval.func('E', expr + ';')
|
||||
//#else */
|
||||
// Now, we can create the function to return by calling the Function constructor.
|
||||
// The parameter `E` is the error handler for runtime only.
|
||||
return new Function('E', expr + ';') // eslint-disable-line no-new-func
|
||||
//#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Compilation
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Regexes for `_getTmpl` and `_parseExpr`
|
||||
var RE_DQUOTE = /\u2057/g
|
||||
var RE_QBMARK = /\u2057(\d+)~/g // string or regex marker, $1: array index
|
||||
|
||||
/**
|
||||
* Parses an expression or template with zero or more expressions enclosed with
|
||||
* the current brackets.
|
||||
*
|
||||
* @param {string} str - Raw template string, without comments
|
||||
* @returns {string} Processed template, ready for evaluation.
|
||||
* @private
|
||||
*/
|
||||
function _getTmpl (str) {
|
||||
var parts = brackets.split(str.replace(RE_DQUOTE, '"'), 1)// get text/expr parts
|
||||
var qstr = parts.qblocks // hidden qblocks
|
||||
var expr
|
||||
|
||||
// We can have almost anything as expressions, except comments... hope
|
||||
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 // every odd element is an expression
|
||||
|
||||
? _parseExpr(expr, 1, qstr) // mode 1 convert falsy values (except false) to "",
|
||||
// except zero
|
||||
: '"' + expr // ttext: convert to js literal string
|
||||
.replace(/\\/g, '\\\\') // this is html, preserve backslashes
|
||||
.replace(/\r\n?|\n/g, '\\n') // normalize eols
|
||||
.replace(/"/g, '\\"') + // escape inner double quotes
|
||||
'"' // enclose in double quotes
|
||||
|
||||
)) list[j++] = expr
|
||||
|
||||
}
|
||||
|
||||
expr = j < 2 ? list[0] // optimize code for 0-1 parts
|
||||
: '[' + list.join(',') + '].join("")'
|
||||
|
||||
} else {
|
||||
|
||||
expr = _parseExpr(parts[1], 0, qstr) // single expressions as raw value
|
||||
}
|
||||
|
||||
// Restore quoted strings and regexes
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an individual expression `{expression}` or shorthand `{name: expression, ...}`
|
||||
*
|
||||
* For shorthand names, riot supports a limited subset of the full w3c/html specs of
|
||||
* non-quoted identifiers (closer to CSS1 that CSS2).
|
||||
*
|
||||
* The regex used for recognition is `-?[_A-Za-z\xA0-\xFF][-\w\xA0-\xFF]*`.
|
||||
*
|
||||
* This regex accepts almost all ISO-8859-1 alphanumeric characters within an html
|
||||
* identifier. Doesn't works with escaped codepoints, but you can use Unicode code points
|
||||
* beyond `\u00FF` by quoting the names (not recommended).
|
||||
*
|
||||
* @param {string} expr - The expression, without brackets
|
||||
* @param {number} asText - 0: raw value, 1: falsy (except false) as "", except 0
|
||||
* @param {Array} qstr - Where to store hidden quoted strings and regexes
|
||||
* @returns {string} Code to evaluate the expression.
|
||||
* @see {@link http://www.w3.org/TR/CSS21/grammar.html#scanner}
|
||||
* {@link http://www.w3.org/TR/CSS21/syndata.html#tokenization}
|
||||
* @private
|
||||
*/
|
||||
function _parseExpr (expr, asText, qstr) {
|
||||
|
||||
// Non-empty quoted strings and literal regexes are hidden at this point.
|
||||
//
|
||||
// Now, this function converts whitespace into compacted spaces and trims
|
||||
// surrounding spaces and some inner tokens, mainly brackets and separators.
|
||||
// We need to convert embedded `\r` and `\n` as these characters breaks
|
||||
// the evaluation.
|
||||
//
|
||||
// WARNING:
|
||||
// Trim and compact is not strictly necessary, but it allows optimized regexes.
|
||||
// Do not touch the next block until you know how/which regexes are affected.
|
||||
|
||||
expr = expr
|
||||
.replace(/\s+/g, ' ').trim()
|
||||
.replace(/\ ?([[\({},?\.:])\ ?/g, '$1')
|
||||
|
||||
if (expr) {
|
||||
var
|
||||
list = [],
|
||||
cnt = 0,
|
||||
match
|
||||
|
||||
// Try to match the first name in the possible shorthand list
|
||||
while (expr &&
|
||||
(match = expr.match(RE_CSNAME)) &&
|
||||
!match.index // index > 0 means error
|
||||
) {
|
||||
var
|
||||
key,
|
||||
jsb,
|
||||
re = /,|([[{(])|$/g
|
||||
|
||||
// Search the next unbracketed comma or the end of 'expr'.
|
||||
// If a openning js bracket is found ($1), skip the block,
|
||||
// if found the end of expr $1 will be empty and the while loop exits.
|
||||
|
||||
expr = RegExp.rightContext // before replace
|
||||
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)
|
||||
}
|
||||
|
||||
// For shorthands, the generated code returns an array with expression-name pairs
|
||||
expr = !cnt ? _wrapExpr(expr, asText)
|
||||
: cnt > 1 ? '[' + list.join(',') + '].join(" ").trim()' : list[0]
|
||||
}
|
||||
|
||||
return expr
|
||||
|
||||
// Skip bracketed block, uses the str value in the closure
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// Matches a varname, excludes object keys. $1: lookahead, $2: variable name
|
||||
// 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(?:[^.[(]|$)/
|
||||
|
||||
/**
|
||||
* Generates code to evaluate an expression avoiding breaking on undefined vars.
|
||||
*
|
||||
* This function include a try..catch block only if needed, if this block is not included,
|
||||
* the generated code has no return statement.
|
||||
*
|
||||
* This `isFinite`, `isNaN`, `Date`, `RegExp`, and `Math` keywords are not wrapped
|
||||
* for context detection (defaults to the global object).
|
||||
*
|
||||
* @param {string} expr - Normalized expression, without brackets
|
||||
* @param {boolean} asText - If trueish, the output is converted to text, not raw values
|
||||
* @param {string} [key] - For shorthands, the key name
|
||||
* @returns {string} Compiled expression.
|
||||
* @private
|
||||
*/
|
||||
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 // check only if needed
|
||||
|
||||
// this, window, and global needs try block too
|
||||
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)) // needs try..catch block?
|
||||
}
|
||||
}
|
||||
return match
|
||||
})
|
||||
|
||||
if (tb) {
|
||||
expr = 'try{return ' + expr + '}catch(e){E(e,this)}'
|
||||
}
|
||||
|
||||
if (key) { // shorthands
|
||||
// w/try : function(){try{return expr}catch(e){E(e,this)}}.call(this)?"name":""
|
||||
// no try: (expr)?"name":""
|
||||
// ==> 'return [' + expr_list.join(',') + '].join(" ").trim()'
|
||||
expr = (tb
|
||||
? 'function(){' + expr + '}.call(this)' : '(' + expr + ')'
|
||||
) + '?"' + key + '":""'
|
||||
|
||||
} else if (asText) {
|
||||
// in multipart expression, falsy values resolve to empty string,
|
||||
// but `false` resolves to `false` instead
|
||||
if (expr === 'false') {
|
||||
expr = 'function(v){' + (tb
|
||||
? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
|
||||
) + ';return false}.call(this)'
|
||||
} else {
|
||||
// w/try : function(v){try{v=expr}catch(e){E(e,this)};return v||v===0?v:""}.call(this)
|
||||
// no try: function(v){return (v=(expr))||v===0?v:""}.call(this)
|
||||
// ==> 'return [' + text_and_expr_list.join(',') + '].join("")'
|
||||
expr = 'function(v){' + (tb
|
||||
? expr.replace('return ', 'v=') : 'v=(' + expr + ')'
|
||||
) + ';return v||v===0||v===false?v:""}.call(this)'
|
||||
}
|
||||
}
|
||||
// else if (!asText)
|
||||
// no try: return expr
|
||||
// w/try : try{return expr}catch(e){E(e,this)} // returns undefined if error
|
||||
|
||||
return expr
|
||||
}
|
||||
|
||||
//#if !NODE
|
||||
_tmpl.version = brackets.version = 'WIP'
|
||||
//#endif
|
||||
|
||||
return _tmpl
|
||||
|
||||
})()
|
||||
7
node_modules/@n8n_io/riot-tmpl/test/.eslintrc.yml
generated
vendored
Normal file
7
node_modules/@n8n_io/riot-tmpl/test/.eslintrc.yml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
env:
|
||||
mocha: true
|
||||
|
||||
globals:
|
||||
tmpl: true
|
||||
brackets: true
|
||||
expect: true
|
||||
71
node_modules/@n8n_io/riot-tmpl/test/browsers.js
generated
vendored
Normal file
71
node_modules/@n8n_io/riot-tmpl/test/browsers.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/* eslint-disable */
|
||||
module.exports = {
|
||||
// Windows
|
||||
bs_ie_9: {
|
||||
'browser' : 'ie',
|
||||
'browser_version' : '9.0',
|
||||
'os' : 'Windows',
|
||||
'os_version' : '7'
|
||||
},
|
||||
bs_ie_10: {
|
||||
'browser' : 'ie',
|
||||
'browser_version' : '10.0',
|
||||
'os' : 'Windows',
|
||||
'os_version' : '7'
|
||||
},
|
||||
bs_ie_11: {
|
||||
'browser' : 'ie',
|
||||
'browser_version' : '11.0',
|
||||
'os' : 'Windows',
|
||||
'os_version' : '7'
|
||||
},
|
||||
bs_edge: {
|
||||
'browser' : 'edge',
|
||||
'browser_version' : '12.0',
|
||||
'os' : 'Windows',
|
||||
'os_version' : '10'
|
||||
},
|
||||
// Mac
|
||||
bs_safari_6: {
|
||||
'browser' : 'safari',
|
||||
'browser_version' : '6.2',
|
||||
'os' : 'OS X',
|
||||
'os_version' : 'Mountain Lion'
|
||||
},
|
||||
bs_safari_7: {
|
||||
'browser' : 'safari',
|
||||
'browser_version' : '7.1',
|
||||
'os' : 'OS X',
|
||||
'os_version' : 'Mavericks'
|
||||
},
|
||||
bs_safari_8: {
|
||||
'browser' : 'safari',
|
||||
'browser_version' : '8.0',
|
||||
'os' : 'OS X',
|
||||
'os_version' : 'Yosemite'
|
||||
},
|
||||
bs_firefox: {
|
||||
'browser' : 'firefox',
|
||||
'os' : 'OS X',
|
||||
'os_version' : 'Yosemite'
|
||||
},
|
||||
bs_iphone_5: {
|
||||
'browserName' : 'iPhone',
|
||||
'device' : 'iPhone 5',
|
||||
'os_version': '6.0',
|
||||
'os': 'ios'
|
||||
},
|
||||
bs_iphone_6: {
|
||||
'browserName' : 'iPhone',
|
||||
'device' : 'iPhone 6',
|
||||
'os_version': '8.0',
|
||||
'os': 'ios'
|
||||
},
|
||||
// Android
|
||||
bs_android_4: {
|
||||
'browserName' : 'android',
|
||||
'device' : 'Samsung Galaxy S5',
|
||||
'os_version': '4.4',
|
||||
'os': 'android'
|
||||
}
|
||||
}
|
||||
48
node_modules/@n8n_io/riot-tmpl/test/karma.conf.js
generated
vendored
Normal file
48
node_modules/@n8n_io/riot-tmpl/test/karma.conf.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
module.exports = function (config) {
|
||||
|
||||
var browsers,
|
||||
customLaunchers = []
|
||||
|
||||
if (process.env.BROWSERSTACK) {
|
||||
customLaunchers = require('./browsers')
|
||||
browsers = Object.keys(customLaunchers)
|
||||
browsers.forEach(function (browser) { customLaunchers[browser].base = 'BrowserStack' })
|
||||
} else {
|
||||
browsers = ['PhantomJS']
|
||||
}
|
||||
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['mocha'],
|
||||
plugins: [
|
||||
'karma-mocha',
|
||||
'karma-coverage',
|
||||
'karma-browserstack-launcher',
|
||||
'karma-phantomjs-launcher'
|
||||
],
|
||||
|
||||
files: [
|
||||
'../node_modules/expect.js/index.js',
|
||||
'../dist/tmpl.js',
|
||||
'specs/core.specs.js',
|
||||
'specs/brackets.specs.js'
|
||||
],
|
||||
|
||||
browsers: browsers,
|
||||
|
||||
customLaunchers: customLaunchers,
|
||||
|
||||
reporters: ['progress', 'coverage'],
|
||||
preprocessors: {
|
||||
'../dist/tmpl.js': ['coverage']
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: '../coverage/',
|
||||
reporters: [{
|
||||
type: 'lcov',
|
||||
subdir: 'report-lcov'
|
||||
}]
|
||||
},
|
||||
singleRun: true
|
||||
})
|
||||
}
|
||||
139
node_modules/@n8n_io/riot-tmpl/test/perf.js
generated
vendored
Normal file
139
node_modules/@n8n_io/riot-tmpl/test/perf.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/* eslint no-console: 0, max-len: 0 */
|
||||
'use strict' // eslint-disable-line
|
||||
|
||||
var
|
||||
version = require('../package.json').version,
|
||||
tmplNew = require('../dist/tmpl').tmpl,
|
||||
tmpl22 = require('./v223/tmpl223.js').tmpl
|
||||
|
||||
var
|
||||
data = { num: 1, str: 'string', date: new Date(), bool: true, item: null },
|
||||
tmplList = [
|
||||
[' { date }', ' ' + data.date],
|
||||
[' { num === 0 ? 0 : num } ', ' ' + data.num + ' '],
|
||||
['<p>\n{str + num}\n</p>', '<p>\nstring1\n</p>'],
|
||||
[' "{ str.slice(0, 3).replace(/t/, \'T\') }" ', ' "sTr" '],
|
||||
[' "{this.num}" ', ' "1" '],
|
||||
['{ !bool } ', ' '],
|
||||
['{} ', ' ']
|
||||
],
|
||||
exprList = [
|
||||
['{ date }', data.date],
|
||||
['{ num === 0 ? 0 : num }', data.num],
|
||||
['<p>{str + num}</p>', '<p>string1</p>'],
|
||||
['{ "-" + str.slice(0, 3).replace(/t/, \'T\') + "-" }', '-sTr-'],
|
||||
['{this.num}', 1],
|
||||
['{ !bool }', false],
|
||||
['{}', undefined]
|
||||
],
|
||||
csList = [
|
||||
['{ foo: num }', 'foo'],
|
||||
['{ foo: num, bar: item }', 'foo'],
|
||||
['{ foo: date.getFullYear() > 2000, bar: str==this.str }', 'foo bar'],
|
||||
['{ foo: str + num }', 'foo']
|
||||
],
|
||||
ex22a, ex22b, ex22c, mem22, tt22 = [],
|
||||
exNewa, exNewb, exNewc, memNew, tt23 = []
|
||||
|
||||
var LOOP = 50000, TMAX = 12, CPAD = 12, NPAD = 11
|
||||
|
||||
console.log()
|
||||
console.log('Testing %d expressions %d times each.', exprList.length + csList.length, LOOP)
|
||||
|
||||
console.log('tmpl v2.2.4 ...')
|
||||
mem22 = [0, 0, 0]
|
||||
testExpr(tmpl22, data, tt22, exprList, mem22)
|
||||
ex22a = tt22.reduce(numsum)
|
||||
testExpr(tmpl22, data, tt22, csList, mem22)
|
||||
ex22b = tt22.reduce(numsum)
|
||||
testExpr(tmpl22, data, tt22, tmplList, mem22)
|
||||
ex22c = tt22.reduce(numsum)
|
||||
|
||||
console.log('tmpl v' + version + ' ...')
|
||||
memNew = [0, 0, 0]
|
||||
testExpr(tmplNew, data, tt23, exprList, memNew, 1)
|
||||
exNewa = tt23.reduce(numsum)
|
||||
testExpr(tmplNew, data, tt23, csList, memNew, 1)
|
||||
exNewb = tt23.reduce(numsum)
|
||||
testExpr(tmplNew, data, tt23, tmplList, memNew, 1)
|
||||
exNewc = tt23.reduce(numsum)
|
||||
|
||||
console.log()
|
||||
console.log('%s tmpl 2.2.4 new v' + version, padr('Results', CPAD))
|
||||
console.log('%s ---------- ----------', replicate('-', CPAD))
|
||||
console.log('%s: %s %s', padr('Expressions', CPAD), padl(ex22a, NPAD), padl(exNewa, NPAD))
|
||||
console.log('%s: %s %s', padr('Shorthands', CPAD), padl(ex22b, NPAD), padl(exNewb, NPAD))
|
||||
console.log('%s: %s %s', padr('Templates', CPAD), padl(ex22c, NPAD), padl(exNewc, NPAD))
|
||||
console.log('%s: %s %s', padr('TOTAL', CPAD), padl(ex22a + ex22b + ex22c, NPAD), padl(exNewa + exNewb + exNewc, NPAD))
|
||||
console.log()
|
||||
console.log('Memory')
|
||||
//console.log('%s: %s %s', padr('Res set size', CPAD), padl(mem22[0], NPAD), padl(memNew[0], NPAD))
|
||||
console.log('%s: %s %s', padr('Heap total', CPAD), padl(mem22[1], NPAD), padl(memNew[1], NPAD))
|
||||
console.log('%s: %s %s', padr('Heap used', CPAD), padl(mem22[2], NPAD), padl(memNew[2], NPAD))
|
||||
console.log()
|
||||
|
||||
console.log('NOTES:')
|
||||
console.log('- Memory used is the difference during the test of the heapTotal info')
|
||||
console.log(' provided by the node process.memoryUsage() function.')
|
||||
console.log('- Execution time in both versions excludes expression compilation.')
|
||||
console.log('- Minimum & maximum times are removed.')
|
||||
|
||||
function testExpr (tmpl, data, times, list, agc) {
|
||||
var ogc, gc1, gc2, gc3
|
||||
times.length = 0
|
||||
global.gc()
|
||||
global.gc()
|
||||
ogc = process.memoryUsage()
|
||||
gc1 = ogc.rss
|
||||
gc2 = ogc.heapTotal
|
||||
gc3 = ogc.heapUsed
|
||||
|
||||
list.forEach(function (pair, idx) {
|
||||
var
|
||||
tt = new Array(TMAX),
|
||||
s, i, j,
|
||||
expr = pair[0]
|
||||
|
||||
s = tmpl(expr, data)
|
||||
//assert(s === pair[1])
|
||||
if (s !== pair[1]) {
|
||||
throw new Error('`' + s + '` in #' + idx + ' is not `' + pair[1] + '`')
|
||||
}
|
||||
|
||||
for (i = 0; i < tt.length; ++i) {
|
||||
tt[i] = Date.now()
|
||||
for (j = 0; j < LOOP; ++j) {
|
||||
s = tmpl(expr, data)
|
||||
}
|
||||
tt[i] = Date.now() - tt[i]
|
||||
}
|
||||
|
||||
// discard min & max times
|
||||
tt.sort(numsort).pop()
|
||||
tt.shift()
|
||||
times[idx] = tt.reduce(numsum)
|
||||
})
|
||||
|
||||
ogc = process.memoryUsage()
|
||||
agc[0] += ogc.rss - gc1
|
||||
agc[1] += ogc.heapTotal - gc2
|
||||
agc[2] += ogc.heapUsed - gc3
|
||||
}
|
||||
|
||||
function numsort (a, b) {
|
||||
return a - b
|
||||
}
|
||||
function numsum (a, b) {
|
||||
return a + b
|
||||
}
|
||||
function replicate (s, n) {
|
||||
return n < 1 ? '' : (new Array(n + 1)).join(s)
|
||||
}
|
||||
function padr (s, n) {
|
||||
s = '' + s
|
||||
return s + replicate(' ', n - s.length)
|
||||
}
|
||||
function padl (s, n) {
|
||||
s = '' + s
|
||||
return replicate(' ', n - s.length) + s
|
||||
}
|
||||
7
node_modules/@n8n_io/riot-tmpl/test/runner.js
generated
vendored
Normal file
7
node_modules/@n8n_io/riot-tmpl/test/runner.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
expect = require('expect.js')
|
||||
tmpl = require('../dist/tmpl').tmpl
|
||||
brackets = require('../dist/tmpl').brackets
|
||||
|
||||
require('./specs/core.specs.js')
|
||||
require('./specs/brackets.specs.js')
|
||||
446
node_modules/@n8n_io/riot-tmpl/test/specs/brackets.specs.js
generated
vendored
Normal file
446
node_modules/@n8n_io/riot-tmpl/test/specs/brackets.specs.js
generated
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
/* eslint max-len: 0 */
|
||||
|
||||
describe('brackets', function () {
|
||||
|
||||
var data = { x: 2, str: 'x', JSON: JSON }
|
||||
|
||||
// send 1 or 2 in 'err' to enable internal information
|
||||
function render (str, dbg) {
|
||||
if (dbg) data._debug_ = 1
|
||||
return tmpl(str, data)
|
||||
}
|
||||
function setBrackets (s) {
|
||||
brackets.set(s)
|
||||
}
|
||||
function resetBrackets () {
|
||||
brackets.set('{ }')
|
||||
}
|
||||
function bracketsPair () {
|
||||
return brackets(0) + ' ' + brackets(1)
|
||||
}
|
||||
|
||||
// reset brackets to defaults
|
||||
after(resetBrackets)
|
||||
beforeEach(resetBrackets)
|
||||
resetBrackets()
|
||||
|
||||
it('default to { } if setting to undefined, null, or an empty string', function () {
|
||||
var ab = [null, '']
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
setBrackets(ab[i])
|
||||
expect(bracketsPair()).to.equal('{ }')
|
||||
expect(render('{ x }')).to.equal(2)
|
||||
}
|
||||
})
|
||||
|
||||
//// custom brackets
|
||||
it('single and multi character custom brackets', function () {
|
||||
|
||||
// single character brackets
|
||||
brackets.set('[ ]')
|
||||
expect(bracketsPair()).to.equal('[ ]')
|
||||
expect(render('[ x ]')).to.equal(2)
|
||||
expect(render('[ str\\[0\\] ]')).to.equal('x')
|
||||
|
||||
// multi character brackets
|
||||
setBrackets('{{ }}')
|
||||
expect(bracketsPair()).to.equal('{{ }}')
|
||||
expect(render('{{ x }}')).to.equal(2)
|
||||
|
||||
// asymmetric brackets
|
||||
setBrackets('${ }')
|
||||
expect(bracketsPair()).to.equal('${ }')
|
||||
expect(render('${ x }')).to.equal(2)
|
||||
})
|
||||
|
||||
describe('using brackets inside expressions', function () {
|
||||
|
||||
it('brackets in expressions can always be escaped', function () {
|
||||
expect(render('{ "\\{ 1 \\}" }')).to.equal('{ 1 }')
|
||||
expect(render('\\{ 1 }')).to.equal('{ 1 }')
|
||||
expect(render('{ "\\}" }')).to.equal('}')
|
||||
expect(render('{ "\\{" }')).to.equal('{')
|
||||
expect(render('{ \\{\\} }')).to.eql({})
|
||||
})
|
||||
|
||||
it('though escaping is optional', function () {
|
||||
expect(render('{ JSON.stringify({ x: 5 }) }')).to.equal('{"x":5}')
|
||||
expect(render('a{ "b{c}d" }e { "{f{f}}" } g')).to.equal('ab{c}de {f{f}} g')
|
||||
|
||||
// for custom brackets as well
|
||||
setBrackets('[ ]')
|
||||
expect(render('a[ "b[c]d" ]e [ "[f[f]]" ] g')).to.equal('ab[c]de [f[f]] g')
|
||||
|
||||
setBrackets('{{ }}')
|
||||
expect(render('a{{ "b{{c}}d" }}e {{ "{f{{f}}}" }} g')).to.equal('ab{{c}}de {f{{f}}} g')
|
||||
expect(render('{{{}}}')).to.eql({})
|
||||
|
||||
setBrackets('{^ ^}')
|
||||
expect(render('{^ "x" ^}')).to.equal('x')
|
||||
expect(render('{^ /{^}/ ^}').source).to.equal(/{^}/.source)
|
||||
|
||||
setBrackets('[[ ]]')
|
||||
expect(render('a[[ "b[[c]]d" ]]e [["[[f[f]]]"]]g[[]]')).to.equal('ab[[c]]de [[f[f]]]g')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
describe('2.2.3', function () {
|
||||
|
||||
it('escaped brackets, some 8 bit, iso-8859-1 characters', function () {
|
||||
var vals = [
|
||||
// source brackets(2) + brackets(3)
|
||||
//['<% %>', '<% %>' ], // angle brackets unsupported from 2.4
|
||||
['{# #}', '{# #}'],
|
||||
['[! !]', '\\[! !\\]'],
|
||||
['·ʃ ʃ', '·ʃ ʃ'],
|
||||
['{$ $}', '{\\$ \\$}'],
|
||||
['_( )_', '_\\( \\)_']
|
||||
]
|
||||
var rs, bb, i
|
||||
|
||||
rs = new RegExp('{x}')
|
||||
setBrackets('{ }') // same as defaults
|
||||
expect(brackets(rs)).to.be(rs) // must returns the same object (to.be)
|
||||
expect(brackets(0)).to.equal('{')
|
||||
expect(brackets(1)).to.equal('}')
|
||||
expect(brackets(2)).to.equal('{')
|
||||
expect(brackets(3)).to.equal('}')
|
||||
|
||||
for (i = 0; i < vals.length; i++) {
|
||||
// set the new brackets pair
|
||||
rs = vals[i]
|
||||
setBrackets(rs[0])
|
||||
bb = rs[0].split(' ')
|
||||
rs = rs[1]
|
||||
expect(brackets(/{ }/g).source).to.equal(rs)
|
||||
expect(brackets(0)).to.equal(bb[0])
|
||||
expect(brackets(1)).to.equal(bb[1]); bb = rs.split(' ')
|
||||
expect(brackets(2)).to.equal(bb[0])
|
||||
expect(brackets(3)).to.equal(bb[1])
|
||||
}
|
||||
})
|
||||
|
||||
//// Better recognition of nested brackets, escaping is almost unnecessary.
|
||||
//// (include escaped version for compatibility)
|
||||
|
||||
describe('escaping is almost unnecessary', function () {
|
||||
|
||||
// ...unless you're doing something very special?
|
||||
it('no problem with brackets inside strings', function () {
|
||||
//, e.g. { "{" } or { "}" }
|
||||
expect(render('a{ "b{" }c')).to.equal('ab{c')
|
||||
expect(render('a{ "b\\{" }c')).to.equal('ab{c')
|
||||
expect(render('a{ "{b" }c')).to.equal('a{bc')
|
||||
expect(render('a{ "\\{b" }c')).to.equal('a{bc')
|
||||
|
||||
expect(render('a{ "b}" }c')).to.equal('ab}c')
|
||||
expect(render('a{ "b\\}" }c')).to.equal('ab}c')
|
||||
expect(render('a{ "}b" }c')).to.equal('a}bc')
|
||||
expect(render('a{ "\\}b" }c')).to.equal('a}bc')
|
||||
|
||||
expect(render('{"{"}')).to.equal('{')
|
||||
expect(render('{"\\{"}')).to.equal('{')
|
||||
expect(render('{"}"}')).to.equal('}')
|
||||
expect(render('{"\\}"}')).to.equal('}')
|
||||
|
||||
expect(render('{{a:"{}}"}}')).to.eql({ a: '{}}' })
|
||||
expect(render('{{a:"{\\}\\}"}}')).to.eql({ a: '{}}' })
|
||||
})
|
||||
|
||||
it('with custom brackets to "[ ]" (bad idea)', function () {
|
||||
setBrackets('[ ]')
|
||||
expect(render('[ str[0] ]')).to.be('x')
|
||||
expect(render('\\[[ str[0] ]]')).to.be('[x]')
|
||||
expect(render('[ [1].pop() ]')).to.be(1)
|
||||
expect(render('a,[["b", "c"]],d')).to.be('a,b,c,d')
|
||||
})
|
||||
|
||||
it('with custom brackets to "( )" (another bad idea)', function () {
|
||||
setBrackets('( )')
|
||||
expect(render('(str.charAt(0))')).to.be('x')
|
||||
expect(render('\\((str.charAt(0)))')).to.be('(x)')
|
||||
expect(render('((1 + 1))')).to.be(2)
|
||||
expect(render('a,(("b"),("c")),d')).to.be('a,c,d')
|
||||
})
|
||||
|
||||
it('with multi character brackets {{ }}, e.g. on "{{{a:1}}}"', function () {
|
||||
setBrackets('{{ }}')
|
||||
// note: '{{{\\}}}' generate Parse error, this equals to '{{ {\\} }}'
|
||||
expect(render('{{{ a:1 }}}')).to.eql({ a: 1 })
|
||||
expect(render('{{{a: {}}}}')).to.eql({ a: {} })
|
||||
expect(render('{{{a: {\\}}}}')).to.eql({ a: {} })
|
||||
expect(render(' {{{}}}')).to.eql(' [object Object]')
|
||||
})
|
||||
|
||||
it('with multi character brackets (( ))', function () {
|
||||
setBrackets('(( ))')
|
||||
expect(render('((({})))')).to.eql({})
|
||||
expect(render('(((("o"))))="o"')).to.be('o="o"')
|
||||
expect(render('((( ("o") )))="o"')).to.be('o="o"')
|
||||
})
|
||||
|
||||
// - you're using asymmetric custom brackets, e.g.: ${ } instead of { }, [ ], {{ }}, <% %>
|
||||
it('with asymmetric brackets, e.g. ${ {a:1} } instead of ${ {a:1\\} }',
|
||||
function () {
|
||||
setBrackets('${ }')
|
||||
expect(render('${ {a:1} }')).to.eql({ a: 1 })
|
||||
expect(render('${ {a:1\\} }')).to.eql({ a: 1 })
|
||||
})
|
||||
|
||||
it('silly brackets? good luck', function () {
|
||||
setBrackets('[ ]]')
|
||||
expect(render('a[ "[]]"]]b')).to.be('a[]]b')
|
||||
expect(render('[[[]]]]')).to.eql([[]])
|
||||
|
||||
setBrackets('( ))')
|
||||
expect(render('a( "b))" ))c')).to.be('ab))c')
|
||||
expect(render('a( (("bc))")) ))')).to.be('abc))')
|
||||
expect(render('a( ("(((b))") ))c')).to.be('a(((b))c')
|
||||
expect(render('a( ("b" + (")c" ))))')).to.be('ab)c') // test skipBracketedPart()
|
||||
})
|
||||
|
||||
it('please find a case when escaping is still needed!', function () {
|
||||
//expect(render).withArgs('{ "}" }').to.throwError()
|
||||
expect(render('{ "}" }')).to.equal('}')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
// end of brackets 2.2.3
|
||||
|
||||
|
||||
describe('2.3.x', function () {
|
||||
|
||||
it('don\'t use characters in the set [\\x00-\\x1F<>a-zA-Z0-9\'",;\\]',
|
||||
function () {
|
||||
expect(setBrackets).withArgs(', ,').to.throwError()
|
||||
expect(setBrackets).withArgs('" "').to.throwError()
|
||||
expect(setBrackets).withArgs('a[ ]a').to.throwError()
|
||||
expect(bracketsPair()).to.be('{ }')
|
||||
})
|
||||
|
||||
it('you can\'t use the pretty <% %> anymore', function () {
|
||||
expect(setBrackets).withArgs('<% %>').to.throwError()
|
||||
})
|
||||
|
||||
it('brackets.array in sync with riot.settings.brackets', function () {
|
||||
var
|
||||
settings = typeof riot === 'undefined' ? {} : riot.settings,
|
||||
str
|
||||
brackets.settings = settings
|
||||
|
||||
settings.brackets = '{{ }}'
|
||||
str = render('{{ x }} and { x }')
|
||||
expect(str).to.be('2 and { x }')
|
||||
|
||||
// restore using riot.settings
|
||||
settings.brackets = '{ }'
|
||||
str = render('\\{{ x }} and { x }')
|
||||
expect(str).to.be('{2} and 2')
|
||||
|
||||
// change again, now with riot.settings
|
||||
settings.brackets = '{{ }}'
|
||||
str = render('{{ x }} and { x }')
|
||||
expect(str).to.be('2 and { x }')
|
||||
|
||||
settings.brackets = undefined
|
||||
str = render('\\{{ x }} and { x } ')
|
||||
expect(str).to.be('{2} and 2 ')
|
||||
|
||||
resetBrackets()
|
||||
})
|
||||
|
||||
it('riot.settings.brackets has immediate effect', function () {
|
||||
var
|
||||
settings,
|
||||
haveRiot
|
||||
resetBrackets()
|
||||
|
||||
brackets.settings.brackets = '$ $'
|
||||
expect(bracketsPair()).to.be('$ $')
|
||||
|
||||
if (typeof riot !== 'undefined' && riot.settings) {
|
||||
expect(riot.settings.brackets).to.be('^ ^')
|
||||
riot.settings.brackets = '^ ^'
|
||||
expect(brackets.settings.brackets).to.be('^ ^')
|
||||
expect(bracketsPair()).to.be('^ ^')
|
||||
haveRiot = true
|
||||
}
|
||||
|
||||
// reasign brackets.settings
|
||||
|
||||
resetBrackets()
|
||||
brackets.settings = settings = {}
|
||||
|
||||
settings.brackets = '^ ^'
|
||||
expect(brackets.settings.brackets).to.be('^ ^')
|
||||
expect(bracketsPair()).to.be('^ ^')
|
||||
|
||||
brackets.settings.brackets = '$ $'
|
||||
expect(settings.brackets).to.be('$ $')
|
||||
expect(bracketsPair()).to.be('$ $')
|
||||
|
||||
brackets.settings = null // reset to {brackets: DEFAULT}
|
||||
|
||||
expect(brackets.settings.brackets).to.be('{ }')
|
||||
expect(bracketsPair()).to.be('{ }')
|
||||
|
||||
if (haveRiot)
|
||||
brackets.settings = riot.settings
|
||||
resetBrackets()
|
||||
})
|
||||
|
||||
it('don\'t use internal functions', function () {
|
||||
var bp
|
||||
setBrackets(null) //to default
|
||||
|
||||
bp = brackets.array(null)
|
||||
expect(bp[0] + bp[1]).to.be('{}')
|
||||
expect(bracketsPair()).to.be('{ }')
|
||||
|
||||
bp = brackets.array('~ ~')
|
||||
expect(bp[0] + bp[1]).to.be('~~')
|
||||
expect(bracketsPair()).to.be('{ }') // must no change
|
||||
})
|
||||
|
||||
describe('brackets.split', function () {
|
||||
|
||||
it('the new kid in the town is a key function', function () {
|
||||
var
|
||||
str = '<tag att="{ a }" expr1={a<1} expr2={a>2}>\n\\{{body}}\r\n</tag>\n'
|
||||
|
||||
resetBrackets() // set brackets to default
|
||||
var a = brackets.split(str)
|
||||
|
||||
expect(a).to.have.length(9)
|
||||
expect(a[1]).to.be(' a ')
|
||||
expect(a[3]).to.be('a<1')
|
||||
expect(a[5]).to.be('a>2')
|
||||
expect(a[6]).to.be('>\n\\{')
|
||||
expect(a[7]).to.be('body')
|
||||
expect(a[8]).to.be('}\r\n</tag>\n')
|
||||
})
|
||||
|
||||
it('serve unescaped template to the tmpl module', function () {
|
||||
var
|
||||
str = '<tag att="{ a }" expr1={a<1} expr2={a>2}>\n\\{{body}}\r\n</tag>\n'
|
||||
|
||||
resetBrackets()
|
||||
var a = brackets.split(str, true)
|
||||
|
||||
expect(a).to.have.length(9)
|
||||
expect(a[6]).to.be('>\n{')
|
||||
})
|
||||
|
||||
it('handle single or double quotes inside quoted expressions', function () {
|
||||
var
|
||||
str = '<tag att1="{"a"}" att2={"a"} att3={\'a\'}>\'{\'a\'}\'</tag>'
|
||||
|
||||
resetBrackets()
|
||||
var a = brackets.split(str, true)
|
||||
var b = a.qblocks
|
||||
|
||||
expect(a).to.have.length(9)
|
||||
expect(a[0]).to.be('<tag att1="')
|
||||
expect(a[8]).to.be('\'</tag>')
|
||||
|
||||
expect(b).to.have.length(4)
|
||||
expect(b[0]).to.be('"a"')
|
||||
expect(b[1]).to.be('"a"')
|
||||
expect(b[2]).to.be("'a'")
|
||||
expect(b[3]).to.be("'a'")
|
||||
})
|
||||
|
||||
it('recognizes difficult literal regexes', function () {
|
||||
var n, p1 = '<p a="', p2 = '">'
|
||||
var atest = [
|
||||
[p1, '{5+3/ /}/}', p2], // <p a="{a+5/ /}/}"> : regex: /}/ (ok, `5+3/ re` == NaN)
|
||||
[p1, '{/[///[]}/}', p2], // <p a="{/[///[]}/}"> : regex: /[///[]}/
|
||||
[p1, '{/\\/[}\\]]/}', p2], // <p a="{/\/[}\]]/}"> : regex: /\/[}\]]/
|
||||
[p1, '{x/y}', '', '{x/g}', p2], // <p a="{x/y}{x/g}"> : NOT regex: /y}{x/g
|
||||
[p1, '{a++/b}', '', '{/i}', p2], // <p a="{a++/b}{/i}"> : NOT regex: /b}{/i
|
||||
[p1, "{''+/b}{/i}", p2], // <p a="{''+/b}{/i}"> : regex: /b}{/i
|
||||
[p1, '{a==/b}{/i}', p2], // <p a="{a==/b}{/i"> : regex: /b}{/i
|
||||
[p1, '{a=/{}}}}/}', p2] // <p a="{a=/{}}}}/"> : regex: /{}}}}/
|
||||
]
|
||||
var qblocks = [
|
||||
'/}/',
|
||||
'/[///[]}/',
|
||||
'/\\/[}\\]]/',
|
||||
undefined,
|
||||
undefined,
|
||||
'/b}{/i',
|
||||
'/b}{/i',
|
||||
'/{}}}}/',
|
||||
]
|
||||
resetBrackets()
|
||||
|
||||
for (n = 0; n < atest.length; ++n) {
|
||||
var a, t = atest[n]
|
||||
a = brackets.split(t.join(''), 1)
|
||||
expect(a).to.have.length(t.length)
|
||||
expect(a[0]).to.be(unq(t[0]))
|
||||
expect(a.qblocks[0]).to.be(qblocks[n])
|
||||
expect(a[2]).to.be(unq(t[2]))
|
||||
}
|
||||
|
||||
function unq (s) { return /^{.*}$/.test(s) ? s.slice(1, -1) : s }
|
||||
})
|
||||
|
||||
})
|
||||
// end of brackets.split
|
||||
|
||||
})
|
||||
// end of brackets 2.4 suite
|
||||
|
||||
})
|
||||
|
||||
describe('regexes', function () {
|
||||
|
||||
it('literal strings with escaped quotes inside (double quotes)', function () {
|
||||
var match = ' """\\"" "x" "a\\" "'.match(brackets.R_STRINGS) // R_STRINGS has global flag
|
||||
|
||||
expect(match).to.have.length(4)
|
||||
expect(match[0]).to.be('""')
|
||||
expect(match[1]).to.be('"\\""')
|
||||
expect(match[2]).to.be('"x"')
|
||||
expect(match[3]).to.be('"a\\" "')
|
||||
})
|
||||
|
||||
it('literal strings with escaped quotes inside (single quotes)', function () {
|
||||
var match = " '''\\'' 'x' 'a\\' '".match(brackets.R_STRINGS) // R_STRINGS has global flag
|
||||
|
||||
expect(match).to.have.length(4)
|
||||
expect(match[0]).to.be("''")
|
||||
expect(match[1]).to.be("'\\''")
|
||||
expect(match[2]).to.be("'x'")
|
||||
expect(match[3]).to.be("'a\\' '")
|
||||
})
|
||||
|
||||
it('multiline javascript comments in almost all forms', function () {
|
||||
var match = ' /* a *//**/ /*/**/ /*//\n*/ /\\*/**/'.match(brackets.R_MLCOMMS)
|
||||
|
||||
expect(match).to.have.length(5)
|
||||
expect(match[0]).to.be('/* a */')
|
||||
expect(match[1]).to.be('/**/')
|
||||
expect(match[2]).to.be('/*/**/')
|
||||
expect(match[3]).to.be('/*//\n*/')
|
||||
expect(match[4]).to.be('/**/')
|
||||
})
|
||||
|
||||
it('no problema with mixed quoted strings and comments', function () {
|
||||
var
|
||||
re = new RegExp(brackets.S_QBLOCKS + '|' + brackets.R_MLCOMMS.source, 'g'),
|
||||
match = ' /* a */"" /*""*/ "/*\\"*/" \\\'/*2*/\\\'\'\''.match(re)
|
||||
|
||||
expect(match).to.have.length(5)
|
||||
expect(match[0]).to.be('/* a */')
|
||||
expect(match[1]).to.be('""')
|
||||
expect(match[2]).to.be('/*""*/')
|
||||
expect(match[3]).to.be('"/*\\"*/"')
|
||||
expect(match[4]).to.be("'/*2*/\\\''") // yes, the match is correct :)
|
||||
})
|
||||
|
||||
})
|
||||
559
node_modules/@n8n_io/riot-tmpl/test/specs/core.specs.js
generated
vendored
Normal file
559
node_modules/@n8n_io/riot-tmpl/test/specs/core.specs.js
generated
vendored
Normal file
@@ -0,0 +1,559 @@
|
||||
/*eslint camelcase: 0, max-len: 0 */
|
||||
/*global globalVar:true */
|
||||
|
||||
globalVar = 5
|
||||
|
||||
var data = {
|
||||
yes: true,
|
||||
no: false,
|
||||
str: 'x',
|
||||
obj: { val: 2 },
|
||||
arr: [2],
|
||||
x: 2,
|
||||
$a: 0,
|
||||
$b: 1,
|
||||
esc: '\'\n\\',
|
||||
abc: { def: 'abc' },
|
||||
fn: function (s) { return ['hi', s].join(' ') },
|
||||
_debug_: 0
|
||||
}
|
||||
|
||||
// avoid to output the console errors
|
||||
function noop() { /* noop */ }
|
||||
|
||||
// send 1 or 2 in 'err' to enable internal information
|
||||
function render (str, dbg) {
|
||||
if (dbg) data._debug_ = 1
|
||||
return tmpl(str, data)
|
||||
}
|
||||
|
||||
describe('riot-tmpl', function () {
|
||||
|
||||
describe('compiles specs', function () {
|
||||
|
||||
//// return values
|
||||
|
||||
it('expressions always return a raw value', function () {
|
||||
expect(render('{ 1 }')).to.equal(1)
|
||||
expect(render('{ x }')).to.equal(2)
|
||||
expect(render('{ str }')).to.equal(data.str)
|
||||
expect(render('{ obj }')).to.equal(data.obj)
|
||||
expect(render('{ arr }')).to.equal(data.arr)
|
||||
expect(render('{ fn }')).to.equal(data.fn)
|
||||
expect(render('{ null }')).to.equal(null)
|
||||
expect(render('{ no }')).to.equal(false)
|
||||
expect(render('{ yes }')).to.equal(true)
|
||||
expect(render('{ $a }')).to.equal(0)
|
||||
})
|
||||
|
||||
it('templates always return a string value', function () {
|
||||
expect(render('{ 1 } ')).to.equal('1 ')
|
||||
expect(render('{ obj } ')).to.equal('[object Object] ')
|
||||
expect(render(' { yes }')).to.equal(' true')
|
||||
})
|
||||
|
||||
//// empty arguments
|
||||
|
||||
it('empty expressions equal to undefined', function () {
|
||||
expect(render()).to.be(undefined)
|
||||
expect(render('{}')).to.be(undefined)
|
||||
expect(render('{ }')).to.be(undefined)
|
||||
})
|
||||
|
||||
it('empty templates equal to empty string', function () {
|
||||
expect(render('')).to.equal('')
|
||||
expect(render('{ } ')).to.equal(' ')
|
||||
})
|
||||
|
||||
//// undefined values
|
||||
|
||||
it('undefined vars are catched in expressions and returns undefined', function () {
|
||||
expect(render('{ nonExistingVar }')).to.be(undefined)
|
||||
data.parent = undefined
|
||||
tmpl.errorHandler = noop
|
||||
expect(render('{ parent.some.thing }')).to.be(undefined)
|
||||
expect(render('{ !nonExistingVar }')).to.equal(true)
|
||||
expect(render('{ nonExistingVar ? "yes" : "no" }')).to.equal('no')
|
||||
expect(render('{ !nonExistingVar ? "yes" : "no" }')).to.equal('yes')
|
||||
tmpl.errorHandler = null
|
||||
delete data.parent
|
||||
})
|
||||
|
||||
it('in templates, falsy values result in empty string, except zero and false', function () {
|
||||
expect(render(' { nonExistingVar }')).to.equal(' ')
|
||||
expect(render(' { no }')).to.equal(' false')
|
||||
expect(render(' { $a }')).to.equal(' 0')
|
||||
expect(render('{false}')).to.equal(false)
|
||||
expect(render(' {false}')).to.equal(' false')
|
||||
})
|
||||
|
||||
//// expressions
|
||||
|
||||
it('expressions are just regular JavaScript', function () {
|
||||
expect(render('{ obj.val }')).to.be(2)
|
||||
expect(render('{ obj["val"] }')).to.be(2)
|
||||
expect(render('{ arr[0] }')).to.be(2)
|
||||
expect(render('{ arr[0]; }')).to.be(2)
|
||||
expect(render('{ arr.pop() }')).to.be(2)
|
||||
expect(render('{ fn(str) }')).to.be('hi x')
|
||||
expect(render('{ yes && "ok" }')).to.be('ok')
|
||||
expect(render('{ no && "ok" }')).to.be(false)
|
||||
expect(render('{ false || null || !no && yes }')).to.be(true)
|
||||
expect(render('{ !no ? "yes" : "no" }')).to.be('yes')
|
||||
expect(render('{ !yes ? "yes" : "no" }')).to.be('no')
|
||||
// expect(render('{ /^14/.test(+new Date()) }')).to.be(true)
|
||||
expect(render('{ typeof Math.random() }')).to.be('number')
|
||||
expect(render('{ fn("there") }')).to.be('hi there')
|
||||
expect(render('{ str == "x" }')).to.be(true)
|
||||
// debugger
|
||||
expect(render('{ /x/.test(str) }')).to.be(true)
|
||||
expect(render('{ true ? "a b c" : "foo" }')).to.be('a b c')
|
||||
expect(render('{ true ? "a \\"b\\" c" : "foo" }')).to.be('a "b" c')
|
||||
expect(render('{ str + " y" + \' z\'}')).to.be('x y z')
|
||||
expect(render('{ esc }')).to.be(data.esc)
|
||||
expect(render('{ $a }')).to.be(0)
|
||||
expect(render('{ $a + $b }')).to.be(1)
|
||||
expect(render('{ this.str }')).to.be('x')
|
||||
})
|
||||
|
||||
it('global variables are not supported in expressions', function () {
|
||||
expect(render('{ globalVar }')).to.be(undefined)
|
||||
})
|
||||
|
||||
it('all comments in expressions are stripped from the output (not anymore)', function () {
|
||||
expect(render('{ /* comment */ /* as*/ }')).to.be(undefined)
|
||||
expect(render('{ 1 /* comment */ + 1 }')).to.equal(2)
|
||||
expect(render('{ 1 /* comment */ + 1 } ')).to.equal('2 ')
|
||||
})
|
||||
|
||||
//// templates
|
||||
|
||||
it('all expressions are evaluted in template', function () {
|
||||
expect(render('{ 1 }{ 1 }')).to.equal('11')
|
||||
expect(render('{ 1 }{ 1 } ')).to.equal('11 ')
|
||||
expect(render(' { 1 }{ 1 }')).to.equal(' 11')
|
||||
expect(render('{ 1 } { 1 }')).to.equal('1 1')
|
||||
})
|
||||
|
||||
it('both templates and expressions are new-line-friendly', function () {
|
||||
expect(render('\n { yes \n ? 2 \n : 4} \n')).to.equal('\n 2 \n')
|
||||
})
|
||||
|
||||
//// class shorthands
|
||||
|
||||
describe('class shorthands', function () {
|
||||
|
||||
it('names can be single-quoted, double-quoted, unquoted', function () {
|
||||
expect(render('{ ok : yes }')).to.equal('ok')
|
||||
expect(render('{ "a" : yes, \'b\': yes, c: yes }')).to.equal('a b c')
|
||||
expect(render('{ a_b-c3: yes }')).to.equal('a_b-c3')
|
||||
})
|
||||
|
||||
it('set multiple cases, test trim', function () {
|
||||
expect(render('{ c0: 0, c1: "x", "c2 c2b": str, c3: "", c4: obj }')).to.be('c1 c2 c2b c4')
|
||||
expect(render('{ c0: 0, c1: false, "c2 c2b": "", c3: null, c4: undefined }')).to.be('')
|
||||
})
|
||||
|
||||
it('set two classes with one expression', function () {
|
||||
expect(render('{ "a b": yes }')).to.equal('a b')
|
||||
})
|
||||
|
||||
it('errors in expressions are catched silently', function () {
|
||||
tmpl.errorHandler = noop
|
||||
expect(render('{ loading: !nonExistingVar.length }')).to.equal('')
|
||||
tmpl.errorHandler = null
|
||||
})
|
||||
|
||||
it('expressions are just regular JavaScript', function () {
|
||||
expect(render('{ a: !no, b: yes }')).to.equal('a b')
|
||||
expect(render('{ y: false || null || !no && yes }')).to.equal('y')
|
||||
expect(render('{ y: 4 > 2 }')).to.equal('y')
|
||||
expect(render('{ y: fn() }')).to.equal('y')
|
||||
expect(render('{ y: str == "x" }')).to.equal('y')
|
||||
expect(render('{ y: new Date() }')).to.equal('y')
|
||||
expect(render('{ y: str[0] }')).to.equal('y')
|
||||
expect(render('<div>{ (2+3)/2 }</div>')).to.equal('<div>2.5</div>')
|
||||
})
|
||||
|
||||
it('even function calls, objects and arrays are no problem', function () {
|
||||
expect(render('{ ok: fn(1, 2) }')).to.equal('ok')
|
||||
expect(render('{ ok: fn([1, 2]) }')).to.equal('ok')
|
||||
expect(render('{ ok: fn({a: 1, b: 1}) }')).to.equal('ok')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
//// new in tmpl 2.2.3
|
||||
|
||||
describe('2.2.3', function () {
|
||||
|
||||
it('few errors in recognizing complex expressions', function () {
|
||||
data.$a = 0
|
||||
data.$b = 0
|
||||
data.parent = { selectedId: 0 }
|
||||
|
||||
//eslint-disable-next-line no-unused-vars
|
||||
data.translate = function (k, v) { return v.value }
|
||||
|
||||
// FIX #784 - The shorthand syntax for class names doesn't support parentheses
|
||||
expect(render('{ primary: (parent.selectedId === $a) }')).to.be('primary')
|
||||
// a bit more of complexity. note: using the comma operator requires parentheses
|
||||
expect(render('{ ok: ($b++, ($a > 0) || ($b & 1)) }')).to.be('ok')
|
||||
// FIX #1916 - Can't access variable without this in riot 2.5
|
||||
expect(render("{translate('key', {value: abc.def})}", 1)).to.be('abc')
|
||||
|
||||
delete data.translate
|
||||
})
|
||||
|
||||
it('unwrapped keywords void, window and global, in addition to `this`', function () {
|
||||
data.$a = 5
|
||||
expect(render('{ ' + (typeof window === 'object' ? 'window' : 'global') + ' }')).to.be.a('object')
|
||||
expect(Object.keys(render('{ ' + (typeof window === 'object' ? 'window' : 'global') + ' }')).length).to.be(0)
|
||||
|
||||
expect(render('{' + (typeof window === 'object' ? 'window' : 'global') + '.globalVar }')).to.be(undefined)
|
||||
expect(render('{ this.$a }')).to.be(5)
|
||||
expect(render('{ void 0 }')).to.be(undefined)
|
||||
data.Date = Date
|
||||
expect(render('{ new Date() }')).to.be.a('object')
|
||||
delete data.Date
|
||||
})
|
||||
|
||||
//// Better recognition of literal regexps inside template and expressions.
|
||||
it('better recognition of literal regexes', function () {
|
||||
expect(render('{ /{}\\/\\n/.source }')).to.be('{}\\/\\n')
|
||||
expect(render('{ ok: /{}\\/\\n/.test("{}\\/\\n") }')).to.be('ok')
|
||||
// handling quotes in regexp is not so complicated :)
|
||||
expect(render('{ /"\'/.source }')).to.be('"\'')
|
||||
expect(render('{ ok: /"\'/.test("\\"\'") }')).to.be('ok') // ok: /"'/.test("\"'")
|
||||
// html template don't have escape
|
||||
expect(render('rex = /"\'/')).to.be('rex = /"\'/') // rex = /\"\'/
|
||||
// no confusion with operators
|
||||
data.x = 2
|
||||
expect(render('{ 10 /x+10/ 1 }')).to.be(15)
|
||||
expect(render('{ x /2+x/ 1 }')).to.be(3)
|
||||
expect(render('{ x /2+"abc".search(/c/) }')).to.be(3)
|
||||
// in expressions, there's no ASI
|
||||
expect(render('{ x\n /2+x/ 1 }')).to.be(3)
|
||||
})
|
||||
|
||||
it('in quoted text, only openning riot brackets need to be escaped!', function () {
|
||||
expect(render('str = "/\\{}\\/\\n/"')).to.be('str = "/{}\\/\\n/"')
|
||||
expect(render('<p str2="\\{foo}">\\{ message }</p>')).to.be('<p str2="{foo}">{ message }</p>')
|
||||
expect(render('str="\\\\{foo}"')).to.be('str="\\{foo}"')
|
||||
})
|
||||
|
||||
//// Better recognition of comments, including empty ones.
|
||||
//// (moved to 2.4, now tmpl does not support comments)
|
||||
|
||||
it('you can include almost anything in quoted shorhand names', function () {
|
||||
expect(render('{ "_\u221A": 1 }')).to.be('_\u221A')
|
||||
expect(render('{ (this["\u221A"] = 1, this["\u221A"]) }')).to.be(1)
|
||||
})
|
||||
|
||||
//// Extra tests
|
||||
|
||||
it('correct handling of quotes', function () {
|
||||
expect(render("{filterState==''?'empty':'notempty'}")).to.be('notempty')
|
||||
expect(render('{ "House \\"Atrides\\" wins" }')).to.be('House "Atrides" wins')
|
||||
expect(render('{ "Leto\'s house" }')).to.be("Leto's house")
|
||||
expect(render("In '{ \"Leto\\\\\\\'s house\" }'")).to.be("In 'Leto\\\'s house'") //« In '{ "Leto\\\'s house" }' » --> In 'Leto\'s house'
|
||||
expect(render('In "{ "Leto\'s house" }"')).to.be('In "Leto\'s house"') //« In "{ "Leto's house" }" » --> In "Leto's house"
|
||||
expect(render('In "{ \'Leto\\\'s house\' }"')).to.be('In "Leto\'s house"') //« In "{ 'Leto\'s house' }" » --> In "Leto's house"
|
||||
})
|
||||
|
||||
//// Consistency?
|
||||
|
||||
it('main inconsistence between expressions and class shorthands are gone', function () {
|
||||
tmpl.errorHandler = noop
|
||||
expect(render('{ !nonExistingVar.foo ? "ok" : "" }')).to.equal(undefined) // ok
|
||||
expect(render('{ !nonExistingVar.foo ? "ok" : "" } ')).to.equal(' ') // ok
|
||||
expect(render('{ ok: !nonExistingVar.foo }')).to.equal('') // ok ;)
|
||||
tmpl.errorHandler = null
|
||||
})
|
||||
|
||||
//// Mac/Win EOL's normalization avoids unexpected results with some editors.
|
||||
//// (moved to 2.4, now tmpl don't touch non-expression parts)
|
||||
|
||||
describe('whitespace', function () {
|
||||
|
||||
it('is compacted to a space in expressions', function () {
|
||||
// you need see at generated code
|
||||
expect(render(' { yes ?\n\t2 : 4} ')).to.be(' 2 ')
|
||||
expect(render('{ \t \nyes !== no\r\n }')).to.be(true)
|
||||
})
|
||||
|
||||
it('is compacted and trimmed in quoted shorthand names', function () {
|
||||
expect(render('{ " \ta\n \r \r\nb\n ": yes }')).to.be('a b')
|
||||
})
|
||||
|
||||
it('is preserved in literal javascript strings', function () {
|
||||
expect(render('{ "\r\n \n \r" }')).to.be('\r\n \n \r')
|
||||
expect(render('{ ok: "\r\n".charCodeAt(0) === 13 }')).to.be('ok')
|
||||
})
|
||||
|
||||
it('eols (mac/win) are normalized to unix in html text', function () {
|
||||
expect(render('\r\n \n \r \n\r')).to.be('\n \n \n \n\n')
|
||||
expect(render('\r\n { \r"\n" } \r\n')).to.be('\n \n \n')
|
||||
// ...even in their quoted parts
|
||||
expect(render('foo="\r\n \n \r"')).to.be('foo="\n \n \n"')
|
||||
expect(render('style="\rtop:0\r\n"')).to.be('style="\ntop:0\n"')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
// end of tmpl 2.2.3
|
||||
|
||||
//// new in tmpl 2.3.0
|
||||
|
||||
describe('2.3.0', function () {
|
||||
|
||||
it('support for 8 bit, ISO-8859-1 charset in shorthand names', function () {
|
||||
expect(render('{ neón: 1 }')).to.be('neón')
|
||||
expect(render('{ -ä: 1 }')).to.be('-ä') // '-ä' is a valid class name
|
||||
expect(render('{ ä: 1 }')).to.be('ä')
|
||||
})
|
||||
|
||||
it('does not wrap global and window object names', function () {
|
||||
var gw = typeof window === 'object' ? 'window' : 'global'
|
||||
|
||||
expect(render('{ ' + gw + '.globalVar }')).to.be(undefined)
|
||||
data.Date = '{}'
|
||||
expect(render('{ +new ' + gw + '.Date() }')).to.be(undefined)
|
||||
delete data.Date
|
||||
})
|
||||
|
||||
it('unwrapped keywords: Infinity, isFinite, isNaN, Date, RegExp and Math', function () {
|
||||
var i, a = ['isFinite', 'isNaN', 'Date', 'RegExp', 'Math']
|
||||
|
||||
data.Infinity = Infinity
|
||||
data.isFinite = isFinite
|
||||
data.isNaN = isNaN
|
||||
data.Date = Date
|
||||
data.RegExp = RegExp
|
||||
data.Math = Math
|
||||
|
||||
expect(render('{ Infinity }')).to.be.a('number')
|
||||
expect(render('{ isFinite(1) }')).to.be(true)
|
||||
expect(render('{ isNaN({}) }')).to.be(true)
|
||||
expect(render('{ Date.parse }')).to.be.a('function')
|
||||
expect(render('{ RegExp.$1 }')).to.be.a('string')
|
||||
expect(render('{ Math.floor(0) }')).to.be.a('number')
|
||||
|
||||
for (i = 0; i < a.length; ++i) {
|
||||
delete data[a[i]]
|
||||
}
|
||||
})
|
||||
|
||||
it('Fix riot#2002 issue with the `JS_VARNAME` regex failing in iOS 9.3.0', function () {
|
||||
data.t = function (s, o) { return s.replace('__storeCount__', o.storeCount) }
|
||||
data.storeCount = 1
|
||||
var result = render("{ t('Please choose from the __storeCount__ stores available', {storeCount: this.storeCount}) }", 1)
|
||||
|
||||
expect(result).to.be('Please choose from the 1 stores available')
|
||||
delete data.t
|
||||
delete data.storeCount
|
||||
})
|
||||
|
||||
describe('support for comments has been dropped', function () {
|
||||
// comments within expresions are converted to spaces, in concordance with js specs
|
||||
it('if included, the expression may work, but...', function () {
|
||||
expect(render('{ typeof/**/str === "string" }')).to.be(true)
|
||||
expect(render('{ 1+/* */+2 }')).to.be(3)
|
||||
|
||||
// comments in template text is preserved
|
||||
expect(render(' /*/* *\/ /**/ ')).to.be(' /*/* *\/ /**/ ')
|
||||
expect(render('/*/* "note" /**/')).to.be('/*/* "note" /**/')
|
||||
|
||||
// riot parse correctamente empty and exotic comments
|
||||
expect(render('{ /**/ }')).to.be(undefined) // empty comment
|
||||
expect(render('{ /*/* *\/ /**/ }')).to.be(undefined) // nested comment sequences
|
||||
expect(render('{ /*dummy*/ }')).to.be(undefined)
|
||||
|
||||
// there's no problem in shorthands
|
||||
expect(render('{ ok: 0+ /*{no: 1}*/ 1 }')).to.be('ok')
|
||||
|
||||
// nor in the template text, comments inside strings are preserved
|
||||
expect(render('{ "/* ok */" }')).to.be('/* ok */')
|
||||
expect(render('{ "/*/* *\/ /**/" }')).to.be('/*/* *\/ /**/')
|
||||
expect(render('{ "/* \\"comment\\" */" }')).to.be('/* "comment" */')
|
||||
})
|
||||
|
||||
it('something like `{ ok:1 /*,no:1*/ } give incorrect result ("no")', function () {
|
||||
expect(render('{ ok: 1 /*, no: 1*/ }')).to.be('no')
|
||||
})
|
||||
|
||||
it('others can break your application, e.g. { ok/**/: 1 }', function () {
|
||||
expect(render).withArgs('{ ok/**/: 1 }').to.throwError()
|
||||
expect(render).withArgs(' { /* comment */ }').to.throwError()
|
||||
})
|
||||
})
|
||||
|
||||
//// error handler
|
||||
|
||||
describe('catch errors in expressions with tmpl.errorHandler', function () {
|
||||
var clearHandler = function () { tmpl.errorHandler = null }
|
||||
|
||||
beforeEach(clearHandler)
|
||||
afterEach(clearHandler)
|
||||
after(clearHandler)
|
||||
|
||||
it('using a custom function', function () {
|
||||
var err
|
||||
|
||||
tmpl.errorHandler = function (e) { err = e }
|
||||
// je, tmpl({x}, NaN) does not generate error... bug or danling var?
|
||||
//console.error('========== >>>> x: ' + x) // error here
|
||||
//console.error('========== >>>> x: ' + global.x) // undefined here
|
||||
err = 0
|
||||
expect(tmpl('{x[0]}'), {}).to.be(undefined) // empty data
|
||||
expect(err instanceof Error).to.be(true)
|
||||
expect(err.riotData).to.eql({ tagName: undefined, _riot_id: undefined })
|
||||
// undefined as parameter for Function.call(`this`) defaults to global
|
||||
err = 0
|
||||
expect(tmpl('{x[0]}')).to.be(undefined)
|
||||
expect(err instanceof Error).to.be(true)
|
||||
expect(err.riotData).to.eql({ tagName: undefined, _riot_id: undefined })
|
||||
})
|
||||
|
||||
it('GOTCHA: null as param for call([this]) defaults to global too', function () {
|
||||
var err
|
||||
|
||||
tmpl.errorHandler = function (e) { err = e }
|
||||
err = 0
|
||||
expect(tmpl('{x[0]}', null)).to.be(undefined)
|
||||
expect(err instanceof Error).to.be(true)
|
||||
expect(err.riotData).to.eql({ tagName: undefined, _riot_id: undefined })
|
||||
})
|
||||
|
||||
it('catching reading property of an undefined variable', function () {
|
||||
var result, err
|
||||
|
||||
tmpl.errorHandler = function (e) { err = e }
|
||||
data.__ = { tagName: 'DIV' }
|
||||
data._riot_id = 1
|
||||
result = render('{ undefinedVar.property }') // render as normal
|
||||
delete data._riot_id
|
||||
delete data.root
|
||||
|
||||
expect(result).to.be(undefined)
|
||||
expect(err instanceof Error).to.be(true)
|
||||
expect(err.riotData).to.eql({ tagName: 'DIV', _riot_id: 1 })
|
||||
})
|
||||
|
||||
it('top level undefined variables (properties) can\'t be catched', function () {
|
||||
var result, err = 0
|
||||
|
||||
tmpl.errorHandler = function (e) { err = e }
|
||||
result = render('{ undefinedVar }') // render as normal
|
||||
expect(result).to.be(undefined)
|
||||
expect(err).to.be.a('number')
|
||||
})
|
||||
|
||||
it('errors only in the user defined error handler (riot/2108)', function () {
|
||||
var result, userErrOutput, defaultErrOutput
|
||||
|
||||
tmpl.errorHandler = function (e) { userErrOutput = e }
|
||||
console.error = function (e) { defaultErrOutput = e }
|
||||
|
||||
data.__ = { tagName: 'DIV' }
|
||||
data._riot_id = 1
|
||||
result = render('{ undefinedVar.property }') // render as normal
|
||||
delete data._riot_id
|
||||
delete data.root
|
||||
|
||||
console.error = function () { /* noop */ } // eslint-disable-line
|
||||
expect(result).to.be(undefined)
|
||||
expect(userErrOutput instanceof Error).to.be(true)
|
||||
expect(userErrOutput.riotData).to.eql({ tagName: 'DIV', _riot_id: 1 })
|
||||
expect(defaultErrOutput).to.be(undefined)
|
||||
})
|
||||
|
||||
it('errors on instantiation of the getter always throws', function () {
|
||||
expect(render).withArgs('{ a: } }').to.throwError() // SintaxError
|
||||
expect(render).withArgs('{ d c:1 }').to.throwError()
|
||||
})
|
||||
|
||||
it('syntax errors on expressions throws exception', function () {
|
||||
expect(render).withArgs('{ a:(1 }').to.throwError() // SintaxError
|
||||
expect(render).withArgs('{ c[0) }').to.throwError()
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
//// helper functions
|
||||
|
||||
describe('new helper functions', function () {
|
||||
|
||||
it('tmpl.loopKeys: extract keys from the value (for `each`)', function () {
|
||||
var i,
|
||||
atest = [
|
||||
'{ studio in studios["Nearby Locations"] }', { key: 'studio', pos: undefined, val: '{studios["Nearby Locations"]}' },
|
||||
'{k,i in item}', { key: 'k', pos: 'i', val: '{item}' },
|
||||
'{ k in i }', { key: 'k', pos: undefined, val: '{i}' },
|
||||
'{^ item in i }', { key: 'item', pos: undefined, val: '{i}' },
|
||||
'{^item,idx in items } ', { key: 'item', pos: 'idx', val: '{items}' },
|
||||
'{ item} ', { val: '{ item}' },
|
||||
'{item', { val: '{item' }, // val is expected
|
||||
'{}', { val: '{}' },
|
||||
'0', { val: '0' }
|
||||
]
|
||||
|
||||
for (i = 0; i < atest.length; i += 2) {
|
||||
expect(tmpl.loopKeys(atest[i])).to.eql(atest[i + 1])
|
||||
}
|
||||
})
|
||||
|
||||
it('tmpl.loopKeys with custom brackets', function () {
|
||||
brackets.set('{{ }}')
|
||||
var i,
|
||||
atest = [
|
||||
'{{k,i in item}}', { key: 'k', pos: 'i', val: '{{item}}' },
|
||||
'{{ k in i }}', { key: 'k', pos: undefined, val: '{{i}}' },
|
||||
'{{^ item in i }}', { key: 'item', pos: undefined, val: '{{i}}' },
|
||||
'{{^item,idx in items }} ', { key: 'item', pos: 'idx', val: '{{items}}' },
|
||||
'{{ item}} ', { val: '{{ item}}' },
|
||||
'{{item', { val: '{{item' }, // val is expected
|
||||
'{{}}', { val: '{{}}' },
|
||||
'0', { val: '0' }
|
||||
]
|
||||
|
||||
for (i = 0; i < atest.length; i += 2) {
|
||||
expect(tmpl.loopKeys(atest[i])).to.eql(atest[i + 1])
|
||||
}
|
||||
brackets.set(null)
|
||||
})
|
||||
|
||||
it('tmpl.hasExpr: test for expression (brackets) existence', function () {
|
||||
expect(tmpl.hasExpr('{}')).to.be(true)
|
||||
expect(tmpl.hasExpr(' {} ')).to.be(true)
|
||||
expect(tmpl.hasExpr('{ 123 } ')).to.be(true)
|
||||
expect(tmpl.hasExpr('"{ "#" }"')).to.be(true)
|
||||
expect(tmpl.hasExpr('"{ " }')).to.be(true)
|
||||
expect(tmpl.hasExpr('\\{ 123 } ')).to.be(true)
|
||||
expect(tmpl.hasExpr(' \\{}')).to.be(true)
|
||||
expect(tmpl.hasExpr(' }{ ')).to.be(false)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
// end of tmpl 2.3.0
|
||||
|
||||
describe('tmpl 3.x', function () {
|
||||
|
||||
it('has beter support for regexes', function () {
|
||||
data.i = { x: 1 }
|
||||
expect(render('<a>{ typeof /5/ }</a>')).to.be('<a>object</a>')
|
||||
expect(render('<a>{ 5*5 /i.x }</a>')).to.be('<a>25</a>')
|
||||
expect(render('<a>{ 5*5 /i.x/1 }</a>')).to.be('<a>25</a>')
|
||||
expect(render('{ 5+/./.lastIndex }')).to.be(5)
|
||||
})
|
||||
|
||||
it('fixes riot#2361', function () {
|
||||
expect(render('<div>{ (2+3)/2 }</div>')).to.be('<div>2.5</div>')
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
215
node_modules/@n8n_io/riot-tmpl/test/v223/tmpl223.js
generated
vendored
Normal file
215
node_modules/@n8n_io/riot-tmpl/test/v223/tmpl223.js
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
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 <b>{x}</b>
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user