json-e
Advanced tools
Comparing version 4.6.0 to 4.7.0
@@ -598,2 +598,5 @@ (function (global, factory) { | ||
testMathOperands("/", left, right); | ||
if (right == 0) { | ||
throw new InterpreterError("division by zero"); | ||
} | ||
return left / right; | ||
@@ -674,10 +677,12 @@ case ("*"): | ||
} | ||
if (left < 0) { | ||
left = array.length + left; | ||
} | ||
if (isArray$3(array) || isString$2(array)) { | ||
if (node.isInterval) { | ||
right = right === null ? array.length : right; | ||
const slice_or_index = (isInterval, value, left, right) => { | ||
if (left < 0) { | ||
left = value.length + left; | ||
if (left < 0) | ||
left = 0; | ||
} | ||
if (isInterval) { | ||
right = right === null ? value.length : right; | ||
if (right < 0) { | ||
right = array.length + right; | ||
right = value.length + right; | ||
if (right < 0) | ||
@@ -692,3 +697,3 @@ right = 0; | ||
} | ||
return array.slice(left, right) | ||
return value.slice(left, right) | ||
} | ||
@@ -698,7 +703,25 @@ if (!isInteger(left)) { | ||
} | ||
if (left >= array.length) { | ||
if (left >= value.length) { | ||
throw new InterpreterError('index out of bounds'); | ||
} | ||
return array[left] | ||
return value[left] | ||
}; | ||
if (isArray$3(array)) { | ||
return slice_or_index(node.isInterval, array, left, right); | ||
} | ||
if (isString$2(array)) { | ||
// If the string is entirely one-byte characters (i.e. ASCII), we can | ||
// simply use `String.prototype.slice`. | ||
/*eslint no-control-regex: "off"*/ | ||
if (/^[\x00-\x7F]*$/.test(array)) { | ||
return slice_or_index(node.isInterval, array, left, right); | ||
} | ||
// Otherwise, we need to convert it to an array of characters first, | ||
// slice that, and convert back. | ||
let res = slice_or_index(node.isInterval, [...array], left, right); | ||
if (isArray$3(res)) { | ||
res = res.join(''); | ||
} | ||
return res; | ||
} | ||
if (!isObject$2(array)) { | ||
@@ -1082,4 +1105,4 @@ throw expectationError(`infix: "[..]"`, 'object, array, or string'); | ||
define('split', builtins, { | ||
minArgs: 1, | ||
variadic: 'string|number', | ||
minArgs: 2, | ||
argumentTests: ['string', 'string|number'], | ||
invoke: (input, delimiter) => input.split(delimiter) | ||
@@ -1346,2 +1369,39 @@ }); | ||
operators.$find = (template, context) => { | ||
const EACH_RE = 'each\\(([a-zA-Z_][a-zA-Z0-9_]*)(,\\s*([a-zA-Z_][a-zA-Z0-9_]*))?\\)'; | ||
checkUndefinedProperties(template, ['\\$find', EACH_RE]); | ||
let value = render(template['$find'], context); | ||
if (!isArray(value)) { | ||
throw new TemplateError('$find value must evaluate to an array'); | ||
} | ||
if (Object.keys(template).length !== 2) { | ||
throw new TemplateError('$find must have exactly two properties'); | ||
} | ||
let eachKey = Object.keys(template).filter(k => k !== '$find')[0]; | ||
let match = /^each\(([a-zA-Z_][a-zA-Z0-9_]*)(,\s*([a-zA-Z_][a-zA-Z0-9_]*))?\)$/.exec(eachKey); | ||
if (!match) { | ||
throw new TemplateError('$find requires each(identifier) syntax'); | ||
} | ||
if (!isString(template[eachKey])) { | ||
throw new TemplateError('each can evaluate string expressions only'); | ||
} | ||
let x = match[1]; | ||
let i = match[3]; | ||
let each = template[eachKey]; | ||
const result = value.find((v, idx) => { | ||
let args = typeof i !== 'undefined' ? {[x]: v, [i]: idx} : {[x]: v}; | ||
if (isTruthy(parse(each, Object.assign({}, context, args)))) { | ||
return render(each, Object.assign({}, context, args)); | ||
} | ||
}); | ||
return result !== undefined ? result : deleteMarker; | ||
}; | ||
operators.$match = (template, context) => { | ||
@@ -1599,3 +1659,3 @@ checkUndefinedProperties(template, ['\\$match']); | ||
let errorLocation = source.length; | ||
throw new SyntaxError(`Found end of string, expected ${terminator}`, | ||
throw new SyntaxError("unterminated ${..} expression", | ||
{start: errorLocation, end: errorLocation}); | ||
@@ -1602,0 +1662,0 @@ } else if (next.kind !== terminator) { |
{ | ||
"name": "json-e", | ||
"version": "4.6.0", | ||
"version": "4.7.0", | ||
"description": "json parameterization module inspired from json-parameterization", | ||
@@ -5,0 +5,0 @@ "main": "./src/index.js", |
@@ -128,4 +128,4 @@ var {BuiltinError} = require('./error'); | ||
define('split', builtins, { | ||
minArgs: 1, | ||
variadic: 'string|number', | ||
minArgs: 2, | ||
argumentTests: ['string', 'string|number'], | ||
invoke: (input, delimiter) => input.split(delimiter) | ||
@@ -132,0 +132,0 @@ }); |
@@ -222,2 +222,39 @@ /* eslint-disable */ | ||
operators.$find = (template, context) => { | ||
const EACH_RE = 'each\\(([a-zA-Z_][a-zA-Z0-9_]*)(,\\s*([a-zA-Z_][a-zA-Z0-9_]*))?\\)'; | ||
checkUndefinedProperties(template, ['\\$find', EACH_RE]); | ||
let value = render(template['$find'], context); | ||
if (!isArray(value)) { | ||
throw new TemplateError('$find value must evaluate to an array'); | ||
} | ||
if (Object.keys(template).length !== 2) { | ||
throw new TemplateError('$find must have exactly two properties'); | ||
} | ||
let eachKey = Object.keys(template).filter(k => k !== '$find')[0]; | ||
let match = /^each\(([a-zA-Z_][a-zA-Z0-9_]*)(,\s*([a-zA-Z_][a-zA-Z0-9_]*))?\)$/.exec(eachKey); | ||
if (!match) { | ||
throw new TemplateError('$find requires each(identifier) syntax'); | ||
} | ||
if (!isString(template[eachKey])) { | ||
throw new TemplateError('each can evaluate string expressions only'); | ||
} | ||
let x = match[1]; | ||
let i = match[3]; | ||
let each = template[eachKey]; | ||
const result = value.find((v, idx) => { | ||
let args = typeof i !== 'undefined' ? {[x]: v, [i]: idx} : {[x]: v}; | ||
if (isTruthy(parse(each, Object.assign({}, context, args)))) { | ||
return render(each, Object.assign({}, context, args)); | ||
} | ||
}); | ||
return result !== undefined ? result : deleteMarker; | ||
} | ||
operators.$match = (template, context) => { | ||
@@ -475,3 +512,3 @@ checkUndefinedProperties(template, ['\\$match']); | ||
let errorLocation = source.length; | ||
throw new SyntaxError(`Found end of string, expected ${terminator}`, | ||
throw new SyntaxError("unterminated ${..} expression", | ||
{start: errorLocation, end: errorLocation}); | ||
@@ -478,0 +515,0 @@ } else if (next.kind !== terminator) { |
@@ -74,2 +74,5 @@ const {isFunction, isObject, isString, isArray, isNumber, isInteger, isTruthy} = require("../src/type-utils"); | ||
testMathOperands("/", left, right); | ||
if (right == 0) { | ||
throw new InterpreterError("division by zero"); | ||
} | ||
return left / right; | ||
@@ -150,10 +153,12 @@ case ("*"): | ||
} | ||
if (left < 0) { | ||
left = array.length + left | ||
} | ||
if (isArray(array) || isString(array)) { | ||
if (node.isInterval) { | ||
right = right === null ? array.length : right; | ||
const slice_or_index = (isInterval, value, left, right) => { | ||
if (left < 0) { | ||
left = value.length + left | ||
if (left < 0) | ||
left = 0; | ||
} | ||
if (isInterval) { | ||
right = right === null ? value.length : right; | ||
if (right < 0) { | ||
right = array.length + right; | ||
right = value.length + right; | ||
if (right < 0) | ||
@@ -168,3 +173,3 @@ right = 0 | ||
} | ||
return array.slice(left, right) | ||
return value.slice(left, right) | ||
} | ||
@@ -174,7 +179,25 @@ if (!isInteger(left)) { | ||
} | ||
if (left >= array.length) { | ||
if (left >= value.length) { | ||
throw new InterpreterError('index out of bounds'); | ||
} | ||
return array[left] | ||
return value[left] | ||
}; | ||
if (isArray(array)) { | ||
return slice_or_index(node.isInterval, array, left, right); | ||
} | ||
if (isString(array)) { | ||
// If the string is entirely one-byte characters (i.e. ASCII), we can | ||
// simply use `String.prototype.slice`. | ||
/*eslint no-control-regex: "off"*/ | ||
if (/^[\x00-\x7F]*$/.test(array)) { | ||
return slice_or_index(node.isInterval, array, left, right); | ||
} | ||
// Otherwise, we need to convert it to an array of characters first, | ||
// slice that, and convert back. | ||
let res = slice_or_index(node.isInterval, [...array], left, right) | ||
if (isArray(res)) { | ||
res = res.join(''); | ||
} | ||
return res; | ||
} | ||
if (!isObject(array)) { | ||
@@ -181,0 +204,0 @@ throw expectationError(`infix: "[..]"`, 'object, array, or string'); |
105769
2869