Comparing version 2.0.0-beta.4 to 2.0.0-beta.5
@@ -129,2 +129,5 @@ ### v2.0.x | ||
- (Fix LibreOffice detection on Windows) | ||
- Accepts non-alphanumeric characters in variables names, values, ... For example, `{d.i💎d}` is allowed | ||
- Improve security in the builder and reduce memory consumption | ||
- Fix crash when markers are next to each over `{d.id}{d.other}` | ||
@@ -131,0 +134,0 @@ |
@@ -226,3 +226,3 @@ | ||
|| typeof d === 'string' && d.length > _value | ||
|| d.constructor === Object && Object.keys(d).length > _value ) { | ||
|| d && d.constructor === Object && Object.keys(d).length > _value ) { | ||
_result = true; | ||
@@ -242,3 +242,3 @@ } | ||
|| typeof d === 'string' && d.length >= _value | ||
|| d.constructor === Object && Object.keys(d).length >= _value ) { | ||
|| d && d.constructor === Object && Object.keys(d).length >= _value ) { | ||
_result = true; | ||
@@ -258,3 +258,3 @@ } | ||
|| typeof d === 'string' && d.length < _value | ||
|| d.constructor === Object && Object.keys(d).length < _value ) { | ||
|| d && d.constructor === Object && Object.keys(d).length < _value ) { | ||
_result = true; | ||
@@ -274,3 +274,3 @@ } | ||
|| typeof d === 'string' && d.length <= _value | ||
|| d.constructor === Object && Object.keys(d).length <= _value ) { | ||
|| d && d.constructor === Object && Object.keys(d).length <= _value ) { | ||
_result = true; | ||
@@ -277,0 +277,0 @@ } |
@@ -40,2 +40,3 @@ var extracter = require('./extracter'); | ||
var _xmlParts = []; | ||
var _xmlResult = ''; | ||
try { | ||
@@ -51,3 +52,4 @@ var _dynamicDescriptor = extracter.splitMarkers(preprocessedMarkers); | ||
}; | ||
_xmlParts = _builder(_obj, options, helper); | ||
_xmlParts = _builder(_obj, options, helper, _builder.builderDictionary); | ||
_xmlResult = builder.assembleXmlParts(_xmlParts, 20, _builder.builderDictionary); // TODO -> adapt the depth of the sort according to the maximum depth in _xmlParts | ||
} | ||
@@ -57,3 +59,2 @@ catch (e) { | ||
} | ||
var _xmlResult = builder.assembleXmlParts(_xmlParts, 20); // TODO -> adapt the depth of the sort according to the maximum depth in _xmlParts | ||
return callback(null, _xmlResult); | ||
@@ -70,2 +71,3 @@ }); | ||
* | ||
* @param {Function} getSafeValue generate safe value accessor | ||
* @param {String} attr. Example 'd.number' | ||
@@ -79,3 +81,3 @@ * @param {Array} formatters. Example [ 'int', 'toFixed(2)' ] | ||
*/ | ||
getFormatterString : function (varName, contextName, formatters, existingFormatters, onlyFormatterWhichInjectXML) { | ||
getFormatterString : function (getSafeValue, varName, contextName, formatters, existingFormatters, onlyFormatterWhichInjectXML) { | ||
var _lineOfCodes = []; | ||
@@ -101,3 +103,3 @@ for (var i = 0; i < formatters.length; i++) { | ||
var _argument = _arguments[j].replace(/^ *'?/, '').replace(/'? *$/, '').replace(/%2c/g, ','); | ||
var _injectedArgument = `'${_argument}'`; | ||
var _injectedArgument = getSafeValue(_argument); | ||
if (_argument.startsWith('.') === true) { | ||
@@ -110,3 +112,3 @@ var _nbPoint = 0; | ||
// TODO warn if undefined variable | ||
_injectedArgument = `helper.getValueOfPath( ${contextName}.parentsData[${_nbPoint-1}], '${_dynamicVariable}') `; | ||
_injectedArgument = 'helper.getValueOfPath( '+contextName+'.parentsData['+(_nbPoint-1)+'], '+getSafeValue(_dynamicVariable)+')'; | ||
} | ||
@@ -140,2 +142,4 @@ _argumentStr += `, ${_injectedArgument}`; | ||
* | ||
* @param {Function} getSafeVar : generate safe variable | ||
* @param {Function} getSafeValue : generate safe value accessor | ||
* @param {array} conditions : array of conditions. Example [{'left':'sort', 'operator':'>', 'right':'10'}] | ||
@@ -148,3 +152,3 @@ * @param {string} codeIfTrue : code to insert if the condition is true. Example 'row = true' | ||
*/ | ||
getFilterString : function (conditions, codeIfTrue, prefix, inverseCondition, forceObjectTested) { | ||
getFilterString : function (getSafeVar, getSafeValue, conditions, codeIfTrue, prefix, inverseCondition, forceObjectTested) { | ||
prefix = prefix || ''; | ||
@@ -173,3 +177,3 @@ if (!codeIfTrue || !(conditions instanceof Array) || conditions.length ===0) { | ||
if (_alreadyDeclaredFilter[_subObjName] === undefined) { | ||
_declareStr += 'var '+_subObjName+'='+_objName+'["'+_obj+'"];\n'; | ||
_declareStr += 'var '+getSafeVar(_subObjName)+'='+getSafeVar(_objName)+'['+getSafeValue(_obj)+'];\n'; | ||
} | ||
@@ -179,14 +183,14 @@ _objName = _subObjName; | ||
if (_attr === 'i') { | ||
var _rightOperator = _condition.right; | ||
var _rightOperator = parseInt(_condition.right, 10); | ||
var _arrayName = _condition.left.parent; | ||
if (parseInt(_condition.right, 10) < 0) { | ||
_rightOperator = _arrayName + '_array_length ' + _condition.right; | ||
_rightOperator = getSafeVar(_arrayName) + '_array_length ' + parseInt(_condition.right, 10); | ||
} | ||
_str += _arrayName + '_i '+_condition.operator + _rightOperator; | ||
_str += getSafeVar(_arrayName) + '_i '+_condition.operator + _rightOperator; | ||
} | ||
else { | ||
if (_alreadyDeclaredFilter[_objName] === undefined) { | ||
_str += _objName + ' && '; | ||
_str += getSafeVar(_objName) + ' && '; | ||
} | ||
_str += _objName+'["'+_attr+'"]'+_condition.operator+_condition.right; | ||
_str += getSafeVar(_objName)+'['+getSafeValue(_attr)+']'+_condition.operator+getSafeValue(helper.removeQuote(_condition.right)); | ||
} | ||
@@ -210,5 +214,6 @@ if (c < conditions.length - 1) { | ||
* @param {integer} sortDepth : description | ||
* @param {array} builderDictionary : xml part coming from template | ||
* @return {string} final result | ||
*/ | ||
assembleXmlParts : function (arrayOfStringPart, sortDepth) { | ||
assembleXmlParts : function (arrayOfStringPart, sortDepth, builderDictionary) { | ||
var _res = ''; | ||
@@ -222,2 +227,3 @@ builder.sortXmlParts(arrayOfStringPart); | ||
var _hideBlock = 0; | ||
var _prevHideBlock = 0; | ||
@@ -235,2 +241,3 @@ // TODO MANAGE sortDepth | ||
var _part = arrayOfStringPart[i]; | ||
var _str = ''; | ||
// Get count value if needed | ||
@@ -245,2 +252,3 @@ builder.getLoopIteration(_loopIds, _part); | ||
} | ||
_prevHideBlock = _hideBlock; | ||
if (_part.hide !== undefined) { | ||
@@ -252,6 +260,15 @@ _hideBlock += (_hideBlock && 1) | _part.hide; | ||
} | ||
if (_hideBlock > 0 ) { | ||
if (_hideBlock > 0 && _prevHideBlock > 0) { | ||
continue; | ||
} | ||
_res += _part.str; | ||
// include "before" XML string all the time, except at the end of if block | ||
if (!(_hideBlock === 0 && _prevHideBlock > 0)) { | ||
_str = _part.bef !== undefined ? builderDictionary[_part.bef] : ''; | ||
} | ||
// include "after" XML string and the value to inject (_part.str) all the time, except at the beginning of if block | ||
if (!(_hideBlock > 0 && _prevHideBlock === 0)) { | ||
_str += _part.str; | ||
_str += _part.aft !== undefined ? builderDictionary[_part.aft] : ''; | ||
} | ||
_res += _str; | ||
@@ -276,3 +293,3 @@ var _depth = _part.pos.length; | ||
if (_part.rowStart===true) { | ||
_rowInfo[_arrayLevel].xmlPos = _res.length - _part.str.length; | ||
_rowInfo[_arrayLevel].xmlPos = _res.length - _str.length; | ||
} | ||
@@ -391,2 +408,54 @@ else if (_part.rowEnd===true) { | ||
/** | ||
* Generate safe and unique variable names generator for builder | ||
* | ||
* @return {Function} a function which generate variable names | ||
*/ | ||
generateSafeJSVariable : function () { | ||
let _dictionary = new Map(); | ||
return (jsVariable) => { | ||
let _alreadyCreatedVar = _dictionary.get(jsVariable); | ||
if (_alreadyCreatedVar !== undefined) { | ||
return _alreadyCreatedVar; | ||
} | ||
let _newVar = '_gV' + _dictionary.size; | ||
_dictionary.set(jsVariable, _newVar); | ||
return _newVar; | ||
}; | ||
}, | ||
/** | ||
* Generate a functions which store and get values coming from insecure | ||
* source (XMl, carbone markers in document, formatters variable, ...) in a dictionary | ||
* | ||
* @param {String} dictionaryName name of the dictionary in the builder function | ||
*/ | ||
generateSafeJSValueAccessor : function (dictionaryName) { | ||
let _dictionaryIndex = new Map(); | ||
let _dictionary = []; | ||
function getIndex (xmlOrConstantValue) { | ||
let _dictIndex = _dictionaryIndex.get(xmlOrConstantValue); | ||
if (_dictIndex !== undefined) { | ||
return _dictIndex; | ||
} | ||
_dictIndex = (_dictionary.push(xmlOrConstantValue) - 1); | ||
_dictionaryIndex.set(xmlOrConstantValue, _dictIndex); | ||
return _dictIndex; | ||
} | ||
return { | ||
// get index where the value or XML part is stored in the dictionary | ||
getIndex : getIndex, | ||
// get the JS code to access securely to a dictionary's value in the builder function | ||
get : function (xmlOrConstantValue) { | ||
let _dictIndex = getIndex(xmlOrConstantValue); | ||
return dictionaryName + '[' + _dictIndex + ']'; | ||
}, | ||
// get the dictionary | ||
getDictionary : function () { | ||
return _dictionary; | ||
} | ||
}; | ||
}, | ||
/** | ||
* Generate a function which will return an array of strings. | ||
@@ -413,5 +482,10 @@ * This array of strings will be sorted and assemble by assembleXmlParts to get final result. | ||
}; | ||
var _getSafeVar = that.generateSafeJSVariable(); | ||
var _dictionaryName = '_dictionary'; | ||
var _safeAccessor = that.generateSafeJSValueAccessor(_dictionaryName); | ||
var _getSafeValue = _safeAccessor.get; | ||
var _getXMLStrIndex = _safeAccessor.getIndex; | ||
_code.add('prev', addIfNotExist.toString()+'\n'+removeFrom.toString()+'\n'); | ||
_code.add('init', "var _strResult = '';\n"); | ||
_code.add('init', 'var _root = (data !== null)?data:{};\n'); | ||
_code.add('init', 'var '+_getSafeVar('_root') + '= (data !== null)?data:{};\n'); | ||
_code.add('init', 'var _strPart = {};\n'); | ||
@@ -437,3 +511,4 @@ _code.add('init', 'var _strParts = [];\n'); | ||
_code.add('main', " 'pos' : [0],\n"); | ||
_code.add('main', " 'str' : '"+_staticData.before + "'\n"); | ||
_code.add('main', " 'str' : '',\n"); | ||
_code.add('main', " 'bef' : "+_getXMLStrIndex(_staticData.before) + '\n'); | ||
_code.add('main', '};\n'); | ||
@@ -459,3 +534,3 @@ _code.add('main', '_strParts.push(_strPart);\n'); | ||
if (_objNameDeclaration !== '_root' ) { | ||
_code.add('init', 'var '+_objNameDeclaration+' = {};\n'); | ||
_code.add('init', 'var '+_getSafeVar(_objNameDeclaration)+' = {};\n'); | ||
} | ||
@@ -467,3 +542,3 @@ } | ||
var _objName = _hierarchy[_objIndex]; | ||
var _realObjName = _dynamicData[_objName].name; | ||
var _realObjName = _getSafeValue(_dynamicData[_objName].name); | ||
var _type = _dynamicData[_objName].type; | ||
@@ -489,16 +564,16 @@ var _objParentName = _dynamicData[_objName].parent; | ||
if (_objName!=='_root') { | ||
_code.add('prev','main', _objName+'='+'('+_objParentName+' !== undefined)?'+_objParentName+'[\''+_realObjName+'\']:{};\n'); | ||
_code.add('prev','main', _getSafeVar(_objName)+'='+'('+_getSafeVar(_objParentName)+' !== undefined)?'+_getSafeVar(_objParentName)+'['+_realObjName+']:{};\n'); | ||
} | ||
} | ||
else if (_type === 'objectInArray') { | ||
var _arrayOfObjectName = _objName+'_array'; | ||
var _arrayOfObjectIndexName = _objName+'_i'; | ||
_code.add('prev','main', 'var ' + _arrayOfObjectName+'='+'('+_objParentName+' !== undefined)? '+_objParentName+'[\''+_realObjName+'\']:[];\n'); | ||
var _arrayOfObjectNameG = _getSafeVar(_objName)+'_array'; | ||
var _arrayOfObjectIndexNameG = _getSafeVar(_objName)+'_i'; | ||
_code.add('prev','main', 'var ' + _arrayOfObjectNameG+'='+'('+_getSafeVar(_objParentName)+' !== undefined)? '+_getSafeVar(_objParentName)+'['+_realObjName+']:[];\n'); | ||
var _conditionToFindObject = _dynamicData[_objName].conditions || []; | ||
var _objNameTemp = _objName+'_temp'; | ||
_code.add('prev', 'main', 'var '+_arrayOfObjectName+'_length = ('+_arrayOfObjectName+' instanceof Array)?'+_arrayOfObjectName+'.length : 0;\n'); | ||
_code.add('prev', 'main', 'for (var '+_arrayOfObjectIndexName+' = 0; '+_arrayOfObjectIndexName+' < '+_arrayOfObjectName+'_length ; '+_arrayOfObjectIndexName+'++) {\n'); | ||
_code.add('prev', 'main', ' var '+_objNameTemp+' = '+_arrayOfObjectName+'['+_arrayOfObjectIndexName+'];\n'); | ||
_code.add('prev', 'main', that.getFilterString(_conditionToFindObject, _objName+'='+_arrayOfObjectName+'['+_arrayOfObjectIndexName+'];\n break;\n', _objNameTemp, false, _objNameTemp)); | ||
_code.add('prev', 'main', 'var '+_arrayOfObjectNameG+'_length = ('+_arrayOfObjectNameG+' instanceof Array)?'+_arrayOfObjectNameG+'.length : 0;\n'); | ||
_code.add('prev', 'main', 'for (var '+_arrayOfObjectIndexNameG+' = 0; '+_arrayOfObjectIndexNameG+' < '+_arrayOfObjectNameG+'_length ; '+_arrayOfObjectIndexNameG+'++) {\n'); | ||
_code.add('prev', 'main', ' var '+_getSafeVar(_objNameTemp)+' = '+_arrayOfObjectNameG+'['+_arrayOfObjectIndexNameG+'];\n'); | ||
_code.add('prev', 'main', that.getFilterString(_getSafeVar, _getSafeValue, _conditionToFindObject, _getSafeVar(_objName)+'='+_arrayOfObjectNameG+'['+_arrayOfObjectIndexNameG+'];\n break;\n', _objNameTemp, false, _objNameTemp)); | ||
_code.add('prev', 'main', '}\n'); | ||
@@ -510,4 +585,4 @@ } | ||
var _posEnd = _dynamicData[_objName].position.end; | ||
var _arrayIndexName = _objName+'_i'; | ||
var _arrayName = _objName+'_array'; | ||
var _arrayIndexNameG = _getSafeVar(_objName)+'_i'; | ||
var _arrayNameG = _getSafeVar(_objName)+'_array'; | ||
var _iterators = _dynamicData[_objName].iterators; | ||
@@ -523,6 +598,6 @@ var _containSpecialIterator = _dynamicData[_objName].containSpecialIterator; | ||
if (_objName!=='_root') { | ||
_code.add('prev', 'main', 'var '+_arrayName+'='+'('+_objParentName+' instanceof Object) ?'+_objParentName+'[\''+_realObjName+'\']:[];\n'); | ||
_code.add('prev', 'main', 'var '+_arrayNameG+'='+'('+ _getSafeVar(_objParentName)+' instanceof Object) ?'+ _getSafeVar(_objParentName)+'['+_realObjName+']:[];\n'); | ||
} | ||
else { | ||
_code.add('prev', 'main', 'var '+_arrayName+'='+ _objName+';\n'); | ||
_code.add('prev', 'main', 'var '+_arrayNameG+'='+ _getSafeVar(_objName)+';\n'); | ||
} | ||
@@ -536,3 +611,4 @@ // keep the end of the array | ||
_code.add('main', " 'pos' : _xmlPos.slice(0, "+(_nbCustomIterator+_arrayDepth*2-1)+'),\n'); | ||
_code.add('main', " 'str' : '"+_beforeStr + "'\n"); | ||
_code.add('main', " 'str' : '',\n"); | ||
_code.add('main', " 'bef' : "+_getXMLStrIndex(_beforeStr) + '\n'); | ||
_code.add('main', '};\n'); | ||
@@ -543,22 +619,22 @@ _code.add('main', '_strParts.push(_strPart);\n'); | ||
_nestedArray.push(_objName); | ||
var _missingIteratorArrayName = _arrayName+'_missingIterators'; | ||
var _missingIteratorArrayNameG = _arrayNameG+'_missingIterators'; | ||
if (_containSpecialIterator===true) { | ||
_missingIteratorArrayName = _arrayName+'_missingIterators'; | ||
_code.add('main' , 'var '+_missingIteratorArrayName+'=[];\n'); | ||
_missingIteratorArrayNameG = _arrayNameG+'_missingIterators'; | ||
_code.add('main' , 'var '+_missingIteratorArrayNameG+'=[];\n'); | ||
} | ||
_code.add('prev','main', 'var '+_arrayName+'_length = 0;\n'); | ||
_code.add('prev','main', 'if ('+_arrayName+' instanceof Array) {\n'); | ||
_code.add('prev','main', _arrayName+'_length = '+_arrayName+'.length;\n'); | ||
_code.add('prev','main', '} else if ('+_arrayName+' instanceof Object) {\n'); | ||
_code.add('prev','main', _arrayName+' = Object.entries('+_arrayName+').map((a) => { return {att : a[0], val : a[1] } });\n'); | ||
_code.add('prev','main', _arrayName+'_length = '+_arrayName+'.length;\n'); | ||
_code.add('prev','main', 'var '+_arrayNameG+'_length = 0;\n'); | ||
_code.add('prev','main', 'if ('+_arrayNameG+' instanceof Array) {\n'); | ||
_code.add('prev','main', _arrayNameG+'_length = '+_arrayNameG+'.length;\n'); | ||
_code.add('prev','main', '} else if ('+_arrayNameG+' instanceof Object) {\n'); | ||
_code.add('prev','main', _arrayNameG+' = Object.entries('+_arrayNameG+').map((a) => { return {att : a[0], val : a[1] } });\n'); | ||
_code.add('prev','main', _arrayNameG+'_length = '+_arrayNameG+'.length;\n'); | ||
_code.add('prev','main', '}\n'); | ||
_code.add('prev','main', 'for (var '+_arrayIndexName+' = 0; '+_arrayIndexName+' < '+_arrayName+'_length '); | ||
_code.add('prev','main', 'for (var '+_arrayIndexNameG+' = 0; '+_arrayIndexNameG+' < '+_arrayNameG+'_length '); | ||
if (_containSpecialIterator===true) { | ||
_code.add( 'main', ' || '+_missingIteratorArrayName+'.length>0'); | ||
_code.add( 'main', ' || '+_missingIteratorArrayNameG+'.length>0'); | ||
} | ||
_code.add('prev','main', ' ; '+_arrayIndexName+'++) {\n'); | ||
_code.add('prev','main', ' var '+_objName+' = '+_arrayName+'['+_arrayIndexName+'];\n'); | ||
_code.add('prev','main', ' ; '+_arrayIndexNameG+'++) {\n'); | ||
_code.add('prev','main', ' var '+ _getSafeVar(_objName)+' = '+_arrayNameG+'['+_arrayIndexNameG+'];\n'); | ||
@@ -568,2 +644,4 @@ // use a custom iterator? | ||
var _iterator = _iterators[it]; | ||
var _iteratorObjG = _getSafeValue(_iterator.obj); | ||
var _iteratorAttrG = _getSafeValue(_iterator.attr); | ||
if (it>0) { | ||
@@ -573,36 +651,36 @@ _nbCustomIterator++; | ||
if (_iterator.attr === 'i') { | ||
_code.add('main', ' _xmlPos['+(_nbCustomIterator+_arrayDepth*2-1)+'] = '+_arrayIndexName+';\n'); | ||
_code.add('main', ' _xmlPos['+(_nbCustomIterator+_arrayDepth*2-1)+'] = '+_arrayIndexNameG+';\n'); | ||
} | ||
else { | ||
var _iteratorName = _objName+'_it'; | ||
var _iteratorObjName = _objName+'_itObj'; | ||
_code.add('prev', 'main', ' var '+_iteratorName+' = 0;\n'); // TODO return errors if the iterator is not defined | ||
var _iteratorNameG = _getSafeVar(_objName)+'_it'; | ||
var _iteratorObjNameG = _getSafeVar(_objName)+'_itObj'; | ||
_code.add('prev', 'main', ' var '+_iteratorNameG+' = 0;\n'); // TODO return errors if the iterator is not defined | ||
if (_containSpecialIterator===true) { | ||
_code.add('main', 'if('+ _objName +' !== undefined){\n'); | ||
_code.add('main', 'if('+ _getSafeVar(_objName) +' !== undefined){\n'); | ||
} | ||
// the iterator is inside an object | ||
if (_iterator.obj !== undefined) { | ||
_code.add('prev','main', ' var '+_iteratorObjName+' = '+_objName+"['"+_iterator.obj+"'];\n"); | ||
_code.add('prev','main', ' if('+_iteratorObjName+' !== undefined) {\n'); | ||
_code.add('prev','main', ' '+_iteratorName+' = '+_iteratorObjName+"['"+_iterator.attr+"'];\n"); | ||
_code.add('prev','main', ' var '+_iteratorObjNameG+' = '+_getSafeVar(_objName)+'['+_iteratorObjG+'];\n'); | ||
_code.add('prev','main', ' if('+_iteratorObjNameG+' !== undefined) {\n'); | ||
_code.add('prev','main', ' '+_iteratorNameG+' = '+_iteratorObjNameG+'['+_iteratorAttrG+'];\n'); | ||
_code.add('prev','main', ' }\n'); | ||
} | ||
else { | ||
_code.add('prev','main', ' '+_iteratorName+' = '+_objName+"['"+_iterator.attr+"'];\n"); | ||
_code.add('prev','main', ' '+_iteratorNameG+' = '+_getSafeVar(_objName)+'['+_iteratorAttrG+'];\n'); | ||
} | ||
if (_containSpecialIterator===true) { | ||
_code.add('main', ' removeFrom('+_missingIteratorArrayName+', '+_iteratorName+');\n'); | ||
_code.add('main', ' removeFrom('+_missingIteratorArrayNameG+', '+_iteratorNameG+');\n'); | ||
_code.add('main', '}else{\n'); | ||
_code.add('main', ' '+_iteratorName+' = '+_missingIteratorArrayName+'.pop();\n'); | ||
_code.add('main', ' '+_iteratorNameG+' = '+_missingIteratorArrayNameG+'.pop();\n'); | ||
_code.add('main', '}\n'); | ||
} | ||
_code.add('main', ' _xmlPos['+(_nbCustomIterator+_arrayDepth*2-1)+'] = '+_iteratorName+';\n'); | ||
_code.add('main', ' _xmlPos['+(_nbCustomIterator+_arrayDepth*2-1)+'] = '+_iteratorNameG+';\n'); | ||
// count the number of custom iterator | ||
// _str += " _xmlPos["+(_nbCustomIterator+_arrayDepth*2-1)+"] = "+_arrayIndexName+";\n"; | ||
// _str += " _xmlPos["+(_nbCustomIterator+_arrayDepth*2-1)+"] = "+_arrayIndexNameG+";\n"; | ||
if (_iterator.isSpecial === true) { | ||
_atLeastOneSpecialIterator = true; | ||
var _allIteratorArrayName = _iteratorName + '_wanted'; | ||
_code.main = _code.main.replace(_missingIteratorArrayName+'=[]', _missingIteratorArrayName+'='+_allIteratorArrayName+'.slice()'); | ||
_code.add('init', 'var '+_allIteratorArrayName+'=[];\n'); | ||
_code.add('prev', ' addIfNotExist('+_allIteratorArrayName+', '+_iteratorName+');\n'); | ||
var _allIteratorArrayNameG = _iteratorNameG + '_wanted'; | ||
_code.main = _code.main.replace(_missingIteratorArrayNameG+'=[]', _missingIteratorArrayNameG+'='+_allIteratorArrayNameG+'.slice()'); | ||
_code.add('init', 'var '+_allIteratorArrayNameG+'=[];\n'); | ||
_code.add('prev', ' addIfNotExist('+_allIteratorArrayNameG+', '+_iteratorNameG+');\n'); | ||
} | ||
@@ -617,2 +695,3 @@ } | ||
var _dataAttr = _xmlPart.attr; | ||
var _dataAttrG = _getSafeValue(_xmlPart.attr); | ||
var _partDepth = _xmlPart.depth; | ||
@@ -630,6 +709,6 @@ var _formatters = _xmlPart.formatters || []; | ||
_code.add('main', " 'pos' : _xmlPos.slice(0, "+(_nbCustomIterator+_partDepth*2+1)+'),\n'); | ||
_code.add('main', " 'str' : ''\n"); | ||
_code.add('main', " 'str' : ''\n"); | ||
_code.add('main', '};\n'); | ||
if (_xmlPart.before) { | ||
_code.add('main', "_strPart.str = '"+_xmlPart.before + "';\n"); | ||
_code.add('main', '_strPart.bef = '+_getXMLStrIndex(_xmlPart.before) + ';\n'); | ||
} | ||
@@ -646,4 +725,4 @@ if (_xmlPart.array === 'start') { | ||
_code.add('main', '_strPart.rowShow = true;\n'); | ||
_code.add('main', that.getFilterString(_conditions, '_strPart.rowShow = false', _objName, true)); | ||
_code.add('main', 'var _str = ' + _dataObj + ' !== undefined && ' + _dataObj + ' !== null ? ' + _dataObj + "['" + _dataAttr + "']" + ' : undefined ;\n'); | ||
_code.add('main', that.getFilterString(_getSafeVar, _getSafeValue, _conditions, '_strPart.rowShow = false', _getSafeVar(_objName), true)); | ||
_code.add('main', 'var _str = ' + _getSafeVar(_dataObj) + ' !== undefined && ' + _getSafeVar(_dataObj) + ' !== null ? ' + _getSafeVar(_dataObj) + '[' + _getSafeValue(_dataAttr) + ']' + ' : undefined ;\n'); | ||
// TODO optimize avoid using all this options for all formatters | ||
@@ -654,4 +733,4 @@ _code.add('main', '_formatterOptions.stopPropagation = false;\n'); | ||
_code.add('main', '_formatterOptions.isHidden = null;\n'); | ||
_code.add('main', '_formatterOptions.parentsData = ['+_dataObj+', '+_objParentNames.join(',')+'];\n'); | ||
_code.add('main', that.getFormatterString('_str', '_formatterOptions', _formatters, existingFormatters, false)); | ||
_code.add('main', '_formatterOptions.parentsData = ['+_getSafeVar(_dataObj)+', '+_objParentNames.map(_getSafeVar).join(',')+'];\n'); | ||
_code.add('main', that.getFormatterString(_getSafeValue, '_str', '_formatterOptions', _formatters, existingFormatters, false)); | ||
// replace null or undefined value by an empty string | ||
@@ -669,3 +748,3 @@ _code.add('main', 'if(_str === null || _str === undefined) {\n'); | ||
// insert formatters which can inject XML, so after .replace(/</g, '<') ... etc | ||
_code.add('main', that.getFormatterString('_str', '_formatterOptions', _formatters, existingFormatters, true)); | ||
_code.add('main', that.getFormatterString(_getSafeValue, '_str', '_formatterOptions', _formatters, existingFormatters, true)); | ||
@@ -675,3 +754,3 @@ _code.add('main', "_strPart.str += (_strPart.rowShow !== false)?_str:''"+';\n'); | ||
if (_xmlPart.after) { | ||
_code.add('main', "_strPart.str += '"+_xmlPart.after + "';\n"); | ||
_code.add('main', '_strPart.aft = ' + _getXMLStrIndex(_xmlPart.after) + ';\n'); | ||
} | ||
@@ -700,3 +779,4 @@ // push the xml part in a array (this array will be sorted at the end) | ||
_code.add('main', " 'pos' : ["+(_keepHighestPosition+1)+'],\n'); | ||
_code.add('main', " 'str' : '"+_staticData.after + "'\n"); | ||
_code.add('main', " 'str' : '',\n"); | ||
_code.add('main', " 'aft' : "+ _getXMLStrIndex(_staticData.after) + '\n'); | ||
_code.add('main', '};\n'); | ||
@@ -715,3 +795,4 @@ _code.add('main', '_strParts.push(_strPart);\n'); | ||
try { | ||
_fn = new Function('data', 'options', 'helper', _codeAssembled); | ||
_fn = new Function('data', 'options', 'helper', _dictionaryName, _codeAssembled); | ||
_fn.builderDictionary = _safeAccessor.getDictionary(); | ||
} | ||
@@ -718,0 +799,0 @@ catch (err) { |
@@ -383,3 +383,3 @@ var parser = require('./parser'); | ||
var _part = _allSortedParts[i]; | ||
var _pos = Math.ceil(_part.pos); // can be a float | ||
var _pos = Math.round(_part.pos); // can be a float | ||
if (i===0) { | ||
@@ -553,16 +553,14 @@ _res.staticData.before = xml.slice(_prevPos, _pos); | ||
var _beginPart = _conditionalBlockDetected.pop(); | ||
if (_beginPart === undefined) { | ||
throw new Error('Missing at least one showBegin or hideBegin'); | ||
} | ||
var _safeXMLBlocks = parser.findSafeConditionalBlockPosition(xml, _beginPart.pos, _part.pos); | ||
// TODO manage when nothing can be removed | ||
if (_safeXMLBlocks.length > 0) { | ||
_newParts.push({ obj : _beginPart.obj, formatters : [], pos : _safeXMLBlocks[0][0] - 0.2 }); | ||
_beginPart.pos = _safeXMLBlocks[0][0] - 0.1; | ||
_part.pos = _safeXMLBlocks[0][1] - 0.2; | ||
_newParts.push({ obj : _beginPart.obj, formatters : [], pos : _safeXMLBlocks[0][1] - 0.1 }); | ||
_part.pos = _safeXMLBlocks[0][1] - 0.1; | ||
for (var j = 1; j < _safeXMLBlocks.length; j++) { | ||
var _safeXMLBlock = _safeXMLBlocks[j]; | ||
// generate empty part before everything to avoid breaking XML with arrays | ||
_newParts.push({ obj : _beginPart.obj, formatters : [] , pos : _safeXMLBlock[0] - 0.2 }); | ||
_newParts.push({ attr : _beginPart.attr, obj : _beginPart.obj, formatters : _beginPart.formatters, pos : _safeXMLBlock[0] - 0.1 }); | ||
_newParts.push({ attr : _beginPart.attr, obj : _beginPart.obj, formatters : _part.formatters , pos : _safeXMLBlock[1] - 0.2 }); | ||
_newParts.push({ obj : _beginPart.obj, formatters : [] , pos : _safeXMLBlock[1] - 0.1 }); | ||
_newParts.push({ attr : _beginPart.attr, obj : _beginPart.obj, formatters : _part.formatters , pos : _safeXMLBlock[1] - 0.1 }); | ||
} | ||
@@ -572,2 +570,5 @@ } | ||
} | ||
if (_conditionalBlockDetected.length > 0) { | ||
throw new Error('Missing at least one showEnd or hideEnd'); | ||
} | ||
descriptor[_objName].xmlParts = descriptor[_objName].xmlParts.concat(_newParts); | ||
@@ -589,4 +590,4 @@ } | ||
if (_obj.type === 'array' && _obj.iterators.length>0) { | ||
var _roughPosStart = descriptor[_objName].position.start; | ||
var _roughPosEnd = descriptor[_objName].position.end; | ||
var _roughPosStart = Math.round(descriptor[_objName].position.start); | ||
var _roughPosEnd = Math.round(descriptor[_objName].position.end); | ||
var _subString = xml.slice(_roughPosStart, _roughPosEnd); | ||
@@ -593,0 +594,0 @@ var _pivot = parser.findPivot(_subString); |
@@ -72,2 +72,15 @@ var fs = require('fs'); | ||
/** | ||
* Remove quotes from string | ||
* | ||
* @param {Strring} str string with or without quotes | ||
* @return {String} string without surrounding quotes | ||
*/ | ||
removeQuote : function (str) { | ||
if (typeof(str) === 'string') { | ||
return str.replace(/^ *['"]?/, '').replace(/['"]? *$/, ''); | ||
} | ||
return str; | ||
}, | ||
/** | ||
* Remove a directory and all its content | ||
@@ -74,0 +87,0 @@ * Be careful, this method is synchrone |
@@ -19,2 +19,3 @@ var helper = require('./helper'); | ||
var _previousMarkerLength = 0; | ||
var _previousMarkerPos = -1; | ||
var _isCarboneMarkerRegexp = /^\{?\s*(?:[cd]\s*[.[:])|\$/; | ||
@@ -53,4 +54,11 @@ var _cleanedXml = xml.replace(/(\r\n|\n|\r)/g,' '); | ||
var _cleanedMarker = that.removeWhitespace(that.cleanMarker(marker)); | ||
var _pos = offset - _previousMarkerLength; | ||
if (_pos === Math.trunc(_previousMarkerPos)) { | ||
// Avoid exactly the same XML position to sort all parts at the end of the process | ||
// Why adding 1/64? to avoid rounding problems of floats (http://0.30000000000000004.com) | ||
// This let us the possibility to have 64 markers at the same position. It should enough for all cases. | ||
_pos = _previousMarkerPos + 1/64; | ||
} | ||
var _obj = { | ||
pos : offset-_previousMarkerLength, | ||
pos : _pos, | ||
name : '_root.'+_cleanedMarker | ||
@@ -60,5 +68,5 @@ }; | ||
_previousMarkerLength += (marker.length + 2); // 2 equals the number of braces '{' or '}' | ||
_previousMarkerPos = _pos; | ||
return ''; | ||
}).replace(/'/g, '\\\''); | ||
process.nextTick(function () { | ||
@@ -654,7 +662,7 @@ callback(null, _cleanedXml, _allMarkers); | ||
var _newCandidates = []; | ||
for (var i = 0; i < _validCandidates.length; i++) { | ||
for (var i = _validCandidates.length - 1; i >= 0; i--) { | ||
var _validCandidate = _validCandidates[i]; | ||
// merge consecutive valid XML-part | ||
if (_lastCandidate !== null && _validCandidate[2] === _lastCandidate[2] && _validCandidate[0] <= _lastCandidate[1]) { | ||
_lastCandidate[1] = _validCandidate[1]; | ||
// merge consecutive valid XML-part, and nested XML part | ||
if (_lastCandidate !== null && _validCandidate[2] >= _lastCandidate[2] && _lastCandidate[0] <= _validCandidate[1] ) { | ||
_lastCandidate[0] = Math.min(_lastCandidate[0], _validCandidate[0]); | ||
} | ||
@@ -666,3 +674,3 @@ else { | ||
} | ||
return _newCandidates; | ||
return _newCandidates.reverse(); | ||
} | ||
@@ -669,0 +677,0 @@ |
{ | ||
"name": "carbone", | ||
"description": "Fast, Simple and Powerful report generator. Injects JSON and produces PDF, DOCX, XLSX, ODT, PPTX, ODS, ...!", | ||
"version": "2.0.0-beta.4", | ||
"version": "2.0.0-beta.5", | ||
"bin": "bin/carbone", | ||
@@ -6,0 +6,0 @@ "main": "./lib", |
@@ -37,2 +37,11 @@ <p align="center"> | ||
> ⚡️ Breaking news : | ||
> | ||
> **Carbone v2.0 BETA 🚀 is available :** | ||
> | ||
> - `npm i carbone@2.0.0-beta.3` | ||
> - Changelog : https://github.com/Ideolys/carbone/blob/v2.0/CHANGELOG.md | ||
> - The final release should be available at the end of May with everything updated (website, and other new features 😛, ...) | ||
## Table of content | ||
@@ -52,6 +61,7 @@ | ||
- [Command line tools](#command-line-tools) | ||
- [Issues](#issues) | ||
- [Roadmap](#roadmap) | ||
- [Performance](#performance) | ||
- [Licenses and editions](#licenses-and-editions) | ||
- [Philosophy](#philosophy) | ||
- [Roadmap](#roadmap) | ||
- [Contributors](#contributors) | ||
@@ -58,0 +68,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
413462
7524
328