todoApp/node_modules/jsonexport/lib/parser/handler.js

210 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* jshint node:true */
'use strict';
const helper = require('../core/helper');
class Handler {
constructor(options) {
this._options = options;
// an object of {typeName:(value,index,parent)=>any}
this._options.typeHandlers = this._options.typeHandlers || {};
}
/**
* Check if results needing mapping to alternate value
*
* @returns [{item, value}] result
*/
_setHeaders(result, item) {
let self = this;
if (!item) return result;
return result.map(function(element) {
element.item = element.item ? item + self._options.headerPathString + element.item : item;
return element;
});
}
castValue(element, item, index, parent){
//cast by matching constructor
const types = this._options.typeHandlers;
for (let type in types ) {
if( isInstanceOfTypeName(element,type) ){
element = types[type].call(types, element, index, parent);
break;//first match we move on
}
}
return element;
}
checkComplex(element, item){
//Check if element is a Date
if (helper.isDate(element)) {
return [{
item: item,
value: (this._options.handleDate || this._handleDate)(element, item),
}];
}
//Check if element is an Array
else if (helper.isArray(element)) {
var resultArray = this._handleArray(element, item);
return this._setHeaders(resultArray, item);
}
//Check if element is a Object
else if (helper.isObject(element)) {
var resultObject = this._handleObject(element);
return this._setHeaders(resultObject, item);
}
return [{
item: item,
value: '',
}];
}
/**
* Check the element type of the element call the correct handle function
*
* @param element Element that will be checked
* @param item Used to make the headers/path breadcrumb
* @returns [{item, value}] result
*/
check(element, item, index, parent) {
element = this.castValue(element, item, index, parent);
// try simple value by highier performance switch
switch(typeof element){
case 'string':
return [{
item: item,
value: this._handleString(element, item),
}];
case 'number':
return [{
item: item,
value: this._handleNumber(element, item),
}];
case 'boolean':
return [{
item: item,
value: this._handleBoolean.bind(this)(element, item),
}];
}
return this.checkComplex(element, item);
}
/**
* Handle all Objects
*
* @param {Object} obj
* @returns [{item, value}] result
*/
_handleObject(obj) {
var result = [];
//Look every object props
for (var prop in obj) {
var propData = obj[prop];
//Check the propData type
var resultCheckType = this.check(propData, prop, prop, obj);
//Append to results aka merge results aka array-append-array
result = result.concat(resultCheckType);
}
return result;
}
/**
* Handle all Arrays, merges arrays with primitive types in a single value
*
* @param {Array} array
* @returns [{item, value}] result
*/
_handleArray(array) {
let self = this;
let result = [];
var firstElementWithoutItem;
for (let aIndex=0; aIndex < array.length; ++aIndex) {
let element = array[aIndex];
//Check the propData type
var resultCheckType = self.check(element, null, aIndex, array);
//Check for results without itens, merge all itens with the first occurrence
if (resultCheckType.length === 0) continue;
var firstResult = resultCheckType[0];
if (!firstResult.item && firstElementWithoutItem !== undefined) {
firstElementWithoutItem.value += self._options.arrayPathString + firstResult.value;
continue;
} else if (resultCheckType.length > 0 && !firstResult.item && firstElementWithoutItem === undefined) {
firstElementWithoutItem = firstResult;
}
//Append to results
result = result.concat(resultCheckType);
}
return result;
}
/**
* Handle all Boolean variables, can be replaced with options.handleBoolean
*
* @param {Boolean} boolean
* @returns {String} result
*/
_handleBoolean(boolean) {
var result;
//Check for booolean options
if (boolean) {
result = this._options.booleanTrueString || 'true';
} else {
result = this._options.booleanFalseString || 'false';
}
return result;
}
/**
* Handle all String variables, can be replaced with options.handleString
*
* @param {String} string
* @returns {String} string
*/
_handleString(string) {
return string;
}
/**
* Handle all Number variables, can be replaced with options.handleNumber
*
* @param {Number} number
* @returns {Number} number
*/
_handleNumber(number) {
return number;
}
/**
* Handle all Date variables, can be replaced with options.handleDate
*
* @param {Date} number
* @returns {string} result
*/
_handleDate(date) {
return date.toLocaleDateString();
}
}
module.exports = Handler;
const globalScope = typeof(window)==="undefined" ? global : window;
function isInstanceOfTypeName(element, typeName){
if( element instanceof globalScope[typeName] ){
return true;//Buffer and complex objects
}
//literals in javascript cannot be checked by instance of
switch( typeof(element) ){
case 'string':return typeName==="String";
case 'boolean':return typeName==="Boolean";
case 'number':return typeName==="Number";
}
return false;
}