Comparing version 2.0.0-beta.5 to 2.0.0-beta.6
@@ -52,4 +52,4 @@ ### v2.0.x | ||
- `ifNEM (value)` : Matches not empty values, string, arrays or objects | ||
- `and (value)` : AND operator between two consecutives conditional formatters | ||
- `or (value)` : (default) OR operator between two consecutives conditional formatters | ||
- `and (value)` : AND operator between two consecutive conditional formatters | ||
- `or (value)` : (default) OR operator between two consecutive conditional formatters | ||
- `hideBegin` and `hideEnd` : hide text block between hideBegin and hideEnd if condition is true | ||
@@ -100,3 +100,3 @@ - `showBegin` and `showEnd` : show a text block between showBegin and showEnd if condition is true | ||
``` | ||
- use .att to print the attribue | ||
- use .att to print the attribute | ||
- use .val to print the value | ||
@@ -120,3 +120,3 @@ | ||
- Eslint code + add eslint tools | ||
- Fix: accepts dashes characters in JSON data. Before, Carbones crashes when using `{d.my-att-with-dash}` | ||
- Fix: accepts dashes characters in JSON data. Before, Carbone crashes when using `{d.my-att-with-dash}` | ||
- Fix: avoid crashing when a XLSX template contains charts | ||
@@ -127,10 +127,11 @@ - Beta: supports dynamic charts rendering in XLSX if these conditions are met: | ||
- all numbers are formatted with formatN() formatter | ||
- Fix: accepts whitespace in array filters with simple quote and double quotes | ||
- Fix: accepts white-space in array filters with simple quote and double quotes | ||
Example: `{d.cars[i, type='Tesla car'].name}` | ||
`{d.cars[i, type="Tesla car"].name}` | ||
- (Fix LibreOffice detection on Windows) | ||
- 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}` | ||
- Fix crash when markers are next to each over `{d.id}{d.other}` | ||
- Accept direct access in arrays such as `{d.myArray[2].val}` instead of `{d.myArray[i=2].val}` | ||
@@ -137,0 +138,0 @@ |
@@ -223,6 +223,6 @@ | ||
// Convert everything in string (not strict Equal) | ||
if ( Number.isNaN(_d) === false && _d > _value | ||
|| d instanceof Array && d.length > _value | ||
|| typeof d === 'string' && d.length > _value | ||
|| d && d.constructor === Object && Object.keys(d).length > _value ) { | ||
if (typeof d === 'number' && _d > _value | ||
|| typeof d === 'string' && value && d.length > value.length | ||
|| Array.isArray(d) === true && value && d.length > value.length | ||
|| d && d.constructor === Object && value && value.constructor === Object && Object.keys(d).length > Object.keys(value).length ) { | ||
_result = true; | ||
@@ -239,6 +239,6 @@ } | ||
// Convert everything in string (not strict Equal) | ||
if ( Number.isNaN(_d) === false && _d >= _value | ||
|| d instanceof Array && d.length >= _value | ||
|| typeof d === 'string' && d.length >= _value | ||
|| d && d.constructor === Object && Object.keys(d).length >= _value ) { | ||
if ( typeof d === 'number' && _d >= _value | ||
|| typeof d === 'string' && value && d.length >= value.length | ||
|| Array.isArray(d) === true && value && d.length >= value.length | ||
|| d && d.constructor === Object && value && value.constructor === Object && Object.keys(d).length >= Object.keys(value).length ) { | ||
_result = true; | ||
@@ -255,6 +255,6 @@ } | ||
// Convert everything in string (not strict Equal) | ||
if ( Number.isNaN(_d) === false && _d < _value | ||
|| d instanceof Array && d.length < _value | ||
|| typeof d === 'string' && d.length < _value | ||
|| d && d.constructor === Object && Object.keys(d).length < _value ) { | ||
if ( typeof d === 'number' && _d < _value | ||
|| typeof d === 'string' && value && d.length < value.length | ||
|| Array.isArray(d) === true && value && d.length < value.length | ||
|| d && d.constructor === Object && value && value.constructor === Object && Object.keys(d).length < Object.keys(value).length ) { | ||
_result = true; | ||
@@ -271,6 +271,6 @@ } | ||
// Convert everything in string (not strict Equal) | ||
if ( Number.isNaN(_d) === false && _d <= _value | ||
|| d instanceof Array && d.length <= _value | ||
|| typeof d === 'string' && d.length <= _value | ||
|| d && d.constructor === Object && Object.keys(d).length <= _value ) { | ||
if ( typeof d === 'number' && _d <= _value | ||
|| typeof d === 'string' && value && d.length <= value.length | ||
|| Array.isArray(d) === true && value && d.length <= value.length | ||
|| d && d.constructor === Object && value && value.constructor === Object && Object.keys(d).length <= Object.keys(value).length ) { | ||
_result = true; | ||
@@ -284,3 +284,3 @@ } | ||
var _result = false; | ||
if ((typeof(d) === 'string' || d instanceof Array) && d.indexOf(value) !== -1) { | ||
if (value && (typeof(d) === 'string' || d instanceof Array) && d.indexOf(value) !== -1) { | ||
_result = true; | ||
@@ -294,3 +294,3 @@ } | ||
var _result = false; | ||
if ((typeof(d) === 'string' || d instanceof Array) && d.indexOf(value) === -1) { | ||
if (value && (typeof(d) === 'string' || d instanceof Array) && d.indexOf(value) === -1) { | ||
_result = true; | ||
@@ -297,0 +297,0 @@ } |
@@ -7,2 +7,3 @@ var path = require('path'); | ||
var debug = require('debug')('carbone:converter'); | ||
var which = require('which'); | ||
@@ -197,2 +198,5 @@ var pythonFile = path.join(__dirname, 'converter.py'); | ||
} | ||
// generate a URL in LibreOffice's format so that it's portable across OSes: | ||
// see: https://wiki.openoffice.org/wiki/URL_Basics | ||
var _userCacheURL = convertToURL(_userCachePath); | ||
@@ -203,3 +207,3 @@ // generate a unique pipe name | ||
var _officeParams = ['--headless', '--invisible', '--nocrashreport', '--nodefault', '--nologo', '--nofirststartwizard', '--norestore', | ||
'--quickstart', '--nolockcheck', '--accept='+_connectionString, '-env:UserInstallation=file://'+_userCachePath ]; | ||
'--quickstart', '--nolockcheck', '--accept='+_connectionString, '-env:UserInstallation='+_userCacheURL ]; | ||
@@ -418,37 +422,161 @@ // save unique name | ||
/** | ||
* Error for path | ||
* | ||
* @param {[type]} message [description] | ||
*/ | ||
function PathError (message) { | ||
this.name = 'PathError'; | ||
this.code = 'PathError'; | ||
this.message = message || 'Failed to convert path'; | ||
if (typeof Error.captureStackTrace === 'function') { | ||
Error.captureStackTrace(this, PathError); | ||
} | ||
} | ||
PathError.prototype = new Error(); | ||
/** | ||
* Convert an absolute path to an absolute URL understood by LibreOffice and | ||
* OpenOffice. This is necessary because LO/OO use a cross-platform path format | ||
* that does not match paths understood natively by OSes. | ||
* If the input is already a URL, it is returned as-is. | ||
* | ||
* @param {string} inputPath - An absolute path to convert to a URL. | ||
* @returns {string} A string suitable for use with LibreOffice as an absolute file path URL. | ||
*/ | ||
function convertToURL (inputPath) { | ||
// Guard clause: if it already looks like a URL, keep it that way. | ||
if (inputPath.slice(0, 8) === 'file:///') { | ||
return inputPath; | ||
} | ||
if (!path.isAbsolute(inputPath)) { | ||
throw new PathError('Paths to convert must be absolute'); | ||
} | ||
// Split into parts so that we can join into a URL: | ||
var _normalizedPath = path.normalize(inputPath); | ||
// (Use both delimiters blindly - we're aiming for maximum compatibility) | ||
var _pathComponents = _normalizedPath.split(/[\\/]/); | ||
// Make sure there is no leading empty element, since we always add a leading "/" anyway. | ||
if (_pathComponents[0] === '') { | ||
_pathComponents.shift(); | ||
} | ||
var outputURL = 'file:///' + _pathComponents.join('/'); | ||
return outputURL; | ||
} | ||
/** | ||
* Detect If LibreOffice and python are available at startup | ||
*/ | ||
function detectLibreOffice () { | ||
if (process.platform === 'darwin') { | ||
// it is better to use the python bundled with LibreOffice | ||
var _path = 'MacOS'; | ||
if (fs.existsSync('/Applications/LibreOffice.app/Contents/' + _path + '/python') === false) { | ||
_path = 'Resources'; | ||
function detectLibreOffice (additionalPaths) { | ||
function _findBundledPython (sofficePath, pythonName) { | ||
if (!sofficePath) { | ||
return null; | ||
} | ||
// Try finding a Python binary shipped alongside the soffice binary, | ||
// either in its actual directory, or - if it's a symbolic link - | ||
// in the directory it points to. | ||
var _sofficeActualDirectory; | ||
var _symlinkDestination; | ||
try { | ||
_symlinkDestination = path.resolve(path.dirname(sofficePath), fs.readlinkSync(sofficePath)); | ||
// Assume symbolic link, will throw in case it's not: | ||
_sofficeActualDirectory = path.dirname(_symlinkDestination); | ||
} | ||
catch (errorToIgnore) { | ||
// Not a symlink. | ||
_sofficeActualDirectory = path.dirname(sofficePath); | ||
} | ||
// Check for the Python binary in the actual soffice path: | ||
try { | ||
return which.sync(pythonName, { path : _sofficeActualDirectory }); | ||
} | ||
catch (errorToIgnore) { | ||
// No bundled Python found. | ||
return null; | ||
} | ||
} | ||
if (fs.existsSync('/Applications/LibreOffice.app/Contents/' + _path + '/python') === true) { | ||
isLibreOfficeFound = true; | ||
converterOptions.pythonExecPath = '/Applications/LibreOffice.app/Contents/' + _path + '/python'; | ||
converterOptions.sofficeExecPath = '/Applications/LibreOffice.app/Contents/MacOS/soffice'; | ||
function _findBinaries (paths, pythonName, sofficeName) { | ||
var _whichPython; | ||
var _whichSoffice; | ||
// Look for the soffice binary - first in the well-known paths, then in | ||
// the system PATH. On Linux, this prioritizes "upstream" (TDF) packages | ||
// over distro-provided ones from the OS' repository. | ||
_whichSoffice = which.sync(sofficeName, { path : paths.join(':'), nothrow : true }) || which.sync(sofficeName, { nothrow : true }) || null; | ||
// Check for a Python binary bundled with soffice, fall back to system-wide: | ||
// This is a bit more complex, since we deal with some corner cases. | ||
// 1. Hopefully use the python from the original soffice package, same dir | ||
// (this might fail on Mac if python is not in MacOS/, but in Resources/). | ||
// 1a. Corner case: on Linux, if soffice was in /usr/bin/soffice and NOT | ||
// a symlink, then we would hit /usr/bin/python, which is probably python2. | ||
// This is why we try with python3 first, to defend against this. | ||
// 2. Try finding it in any of the well-known paths - this might result in | ||
// using Python from *another install* of LibreOffice, but it should be ok. | ||
// This is only attempted if the paths exist on this system to avoid | ||
// a fallback to system PATH that "which" does when passed an empty string. | ||
// 3. Fall back to system python (hopefully named python3). | ||
_whichPython = _findBundledPython(_whichSoffice, 'python3') || | ||
_findBundledPython(_whichSoffice, 'python') || | ||
(paths.length > 0 && which.sync('python3', { path : paths.join(':'), nothrow : true })) || | ||
(paths.length > 0 && which.sync('python', { path : paths.join(':'), nothrow : true })) || | ||
which.sync('python3', { nothrow : true }) || | ||
which.sync('python', { nothrow : true }) || null; | ||
return { | ||
soffice : _whichSoffice, | ||
python : _whichPython | ||
}; | ||
} | ||
function _listProgramDirectories (basePath, pattern) { | ||
try { | ||
return fs.readdirSync(basePath).filter(function _isLibreOfficeDirectory (dirname) { | ||
return pattern.test(dirname); | ||
}).map(function _buildFullProgramPath (dirname) { | ||
return path.join(basePath, dirname, 'program'); | ||
}); | ||
} | ||
catch (errorToIgnore) { | ||
return []; | ||
} | ||
} | ||
var _pathsToCheck = additionalPaths || []; | ||
// overridable file names to look for in the checked paths: | ||
var _pythonName = 'python'; | ||
var _sofficeName = 'soffice'; | ||
var _linuxDirnamePattern = /^libreoffice\d+\.\d+$/; | ||
var _windowsDirnamePattern = /^LibreOffice( \d+(?:\.\d+)*?)?$/i; | ||
if (process.platform === 'darwin') { | ||
_pathsToCheck = _pathsToCheck.concat([ | ||
// It is better to use the python bundled with LibreOffice: | ||
'/Applications/LibreOffice.app/Contents/MacOS', | ||
'/Applications/LibreOffice.app/Contents/Resources' | ||
]); | ||
} | ||
else if (process.platform === 'linux') { | ||
var directories = fs.readdirSync('/opt'); | ||
var patternLibreOffice = /libreoffice\d+\.\d+/; | ||
for (var i = 0; i < directories.length; i++) { | ||
if (patternLibreOffice.test(directories[i]) === true) { | ||
var directoryLibreOffice = '/opt/' + directories[i] + '/program'; | ||
if (fs.existsSync(directoryLibreOffice + '/python') === true) { | ||
converterOptions.pythonExecPath = directoryLibreOffice + '/python'; | ||
converterOptions.sofficeExecPath = directoryLibreOffice + '/soffice'; | ||
isLibreOfficeFound = true; | ||
} | ||
} | ||
} | ||
// The Document Foundation packages (.debs, at least) install to /opt, | ||
// into a directory named after the contained LibreOffice version. | ||
// Add any existing directories that match this to the list. | ||
_pathsToCheck = _pathsToCheck.concat(_listProgramDirectories('/opt', _linuxDirnamePattern)); | ||
} | ||
else if (process.platform === 'win32') { | ||
_pathsToCheck = _pathsToCheck | ||
.concat(_listProgramDirectories('C:\\Program Files', _windowsDirnamePattern)) | ||
.concat(_listProgramDirectories('C:\\Program Files (x86)', _windowsDirnamePattern)); | ||
_pythonName = 'python.exe'; | ||
} | ||
else { | ||
debug('your platform is not supported yet'); | ||
debug('your platform "%s" is not supported yet', process.platform); | ||
} | ||
// Common logic for all OSes: perform the search and save results as options: | ||
var _foundPaths = _findBinaries(_pathsToCheck, _pythonName, _sofficeName); | ||
if (_foundPaths.soffice) { | ||
debug('LibreOffice found: soffice at %s, python at %s', _foundPaths.soffice, _foundPaths.python); | ||
isLibreOfficeFound = true; | ||
converterOptions.pythonExecPath = _foundPaths.python; | ||
converterOptions.sofficeExecPath = _foundPaths.soffice; | ||
} | ||
if (isLibreOfficeFound === false) { | ||
@@ -459,3 +587,2 @@ debug('cannot find LibreOffice. Document conversion cannot be used'); | ||
detectLibreOffice(); | ||
@@ -462,0 +589,0 @@ |
@@ -135,5 +135,10 @@ var parser = require('./parser'); | ||
if (_isArray === true) { | ||
// detect array condition | ||
var _result = /([^,!]+)(!=|=|>|<)([\s\S]+)[,\]]$/.exec(_word); | ||
// detect array condition, or direct access in arrays such as myAarray[10] | ||
var _result = /([^,!]+)(!=|=|>|<)([\s\S]+)[,\]]$/.exec(_word) || /(\d+)\]$/.exec(_word); | ||
// detect direct | ||
if (_result instanceof Array) { | ||
if (_result.length === 2) { | ||
// if this is a direct access such as "myArray[10]", adapt the result as if it was "myArray[i=10]" | ||
_result = [0, 'i', '=', _result[1]]; | ||
} | ||
var _operator = (_result[2] === '=') ? '==' : _result[2]; | ||
@@ -140,0 +145,0 @@ var _conditionObj = { |
@@ -68,3 +68,3 @@ var helper = require('./helper'); | ||
return ''; | ||
}).replace(/'/g, '\\\''); | ||
}); | ||
process.nextTick(function () { | ||
@@ -71,0 +71,0 @@ callback(null, _cleanedXml, _allMarkers); |
{ | ||
"name": "carbone", | ||
"description": "Fast, Simple and Powerful report generator. Injects JSON and produces PDF, DOCX, XLSX, ODT, PPTX, ODS, ...!", | ||
"version": "2.0.0-beta.5", | ||
"version": "2.0.0-beta.6", | ||
"bin": "bin/carbone", | ||
@@ -23,3 +23,4 @@ "main": "./lib", | ||
"lint": "eslint ./*/**.js", | ||
"lint:fix": "eslint ./*/**.js --fix" | ||
"lint:fix": "eslint ./*/**.js --fix", | ||
"postpublish" : "PACKAGE_VERSION=$(cat package.json | grep \\\"version\\\" | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag $PACKAGE_VERSION && git push origin --tags && git push github-origin --tags" | ||
}, | ||
@@ -31,2 +32,3 @@ "dependencies": { | ||
"timsort": "=0.3.0", | ||
"which": "=2.0.2", | ||
"yauzl": "=2.8.0" | ||
@@ -33,0 +35,0 @@ }, |
@@ -41,5 +41,5 @@ <p align="center"> | ||
> | ||
> - `npm i carbone@2.0.0-beta.3` | ||
> - `npm i carbone@2.0.0-beta.5` | ||
> - 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 😛, ...) | ||
> - The final release will be available before mid-June with everything updated (website, and other new features 😛, ...) | ||
@@ -46,0 +46,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
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
418019
7604
6
32
+ Addedwhich@=2.0.2