jupyter-ijavascript-utils 1.14.2 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +4 -1
- package/README.md +2 -1
- package/package.json +1 -1
- package/src/TableGenerator.js +6 -20
- package/src/format.js +69 -0
- package/src/object.js +81 -1
package/DOCS.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Overview
|
|
2
2
|
|
|
3
|
-
This is a
|
|
3
|
+
This is a library to help people that understand JavaScript
|
|
4
|
+
to leverage for using Jupyter with the iJavaScript kernel
|
|
5
|
+
as a way to load and explore data, and ultimately tell compelling stories with visuals.
|
|
4
6
|
|
|
5
7
|
Jupyter is a way to programmatically explore a subject and interleave text and markdown to make Data Driven Documents.
|
|
6
8
|
|
|
@@ -44,6 +46,7 @@ This is not intended to be the only way to accomplish many of these tasks, and a
|
|
|
44
46
|
|
|
45
47
|
## What's New
|
|
46
48
|
|
|
49
|
+
* 1.15 - provide {@link module:object.formatProperties|object.formatProperties} - as a way to quickly convert to string, number, etc.
|
|
47
50
|
* 1.14 - provide {@link module:object.mapProperties|object.mapProperties()} and {@link module:format.compactNumber|format.compactNumber()}
|
|
48
51
|
* 1.13 - provide {@link module:random|utils.random()} to genrate random values
|
|
49
52
|
* 1.12 - provide `utils.table(...)` instead of `new utils.TableGenerator(...)`
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</a>
|
|
8
8
|
<img src="https://img.shields.io/badge/Coverage-98-green" />
|
|
9
9
|
<a href="https://github.com/paulroth3d/jupyter-ijavascript-utils" alt="npm">
|
|
10
|
-
<img src="https://img.shields.io/badge/npm-%5E1.
|
|
10
|
+
<img src="https://img.shields.io/badge/npm-%5E1.15-red" />
|
|
11
11
|
</a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -46,6 +46,7 @@ This is not intended to be the only way to accomplish many of these tasks, and a
|
|
|
46
46
|
|
|
47
47
|
# What's New
|
|
48
48
|
|
|
49
|
+
* 1.15 - provide object.formatProperties - as a way to quickly convert to string, number, etc.
|
|
49
50
|
* 1.14 - provide format.compactNumber and object.mapProperties
|
|
50
51
|
* 1.13 - provide utils.random() to genrate random values
|
|
51
52
|
* 1.12 - provide `utils.table(...)` instead of `new utils.TableGenerator(...)`
|
package/package.json
CHANGED
package/src/TableGenerator.js
CHANGED
|
@@ -18,6 +18,8 @@ const IJSUtils = require('./ijs');
|
|
|
18
18
|
|
|
19
19
|
const ArrayUtils = require('./array');
|
|
20
20
|
|
|
21
|
+
const FormatUtils = require('./format');
|
|
22
|
+
|
|
21
23
|
const { createSort } = require('./array');
|
|
22
24
|
|
|
23
25
|
/**
|
|
@@ -613,27 +615,11 @@ class TableGenerator {
|
|
|
613
615
|
return this;
|
|
614
616
|
}
|
|
615
617
|
|
|
618
|
+
const cleanedFormatter = FormatUtils.prepareFormatterObject(obj);
|
|
619
|
+
|
|
616
620
|
const fnMap = new Map();
|
|
617
|
-
Object.getOwnPropertyNames(
|
|
618
|
-
|
|
619
|
-
let fn;
|
|
620
|
-
const str = obj[key].toLowerCase();
|
|
621
|
-
if (str === 'string') {
|
|
622
|
-
fn = (val) => String(val);
|
|
623
|
-
} else if (str === 'number') {
|
|
624
|
-
fn = (val) => Number(val);
|
|
625
|
-
} else if (str === 'boolean') {
|
|
626
|
-
fn = (val) => val ? 'true' : 'false';
|
|
627
|
-
} else {
|
|
628
|
-
throw Error(`TableGenerator.format: property ${key} formatter of ${str} is unsupported. Only (String, Number, Boolean) are supported`);
|
|
629
|
-
}
|
|
630
|
-
fnMap.set(key, fn);
|
|
631
|
-
} else {
|
|
632
|
-
if ((typeof obj[key]) !== 'function') {
|
|
633
|
-
throw (Error(`Formatter properties must be functions. [${key}]`));
|
|
634
|
-
}
|
|
635
|
-
fnMap.set(key, obj[key]);
|
|
636
|
-
}
|
|
621
|
+
Object.getOwnPropertyNames(cleanedFormatter).forEach((key) => {
|
|
622
|
+
fnMap.set(key, cleanedFormatter[key]);
|
|
637
623
|
});
|
|
638
624
|
|
|
639
625
|
this.#formatterFn = ({ value, property }) => fnMap.has(property)
|
package/src/format.js
CHANGED
|
@@ -632,3 +632,72 @@ module.exports.compactNumber = function compactNumber(num, digits = 0) {
|
|
|
632
632
|
|
|
633
633
|
return (num / siValue).toFixed(digits) + siKey;
|
|
634
634
|
};
|
|
635
|
+
|
|
636
|
+
module.exports.safeConvertString = function safeConvertString(val) {
|
|
637
|
+
try {
|
|
638
|
+
return String(val);
|
|
639
|
+
} catch (err) {
|
|
640
|
+
//-- I cannot find a way to reliably throw an error, but keep it in case it does
|
|
641
|
+
/* istanbul ignore next */
|
|
642
|
+
return null;
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
module.exports.safeConvertFloat = function safeConvertFloat(val) {
|
|
647
|
+
try {
|
|
648
|
+
return Number.parseFloat(val);
|
|
649
|
+
} catch (err) {
|
|
650
|
+
//-- I cannot find a way to reliably throw an error, but keep it in case it does
|
|
651
|
+
/* istanbul ignore next */
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
module.exports.safeConvertInteger = function safeConvertInteger(val) {
|
|
657
|
+
try {
|
|
658
|
+
return Number.parseInt(val, 10);
|
|
659
|
+
} catch (err) {
|
|
660
|
+
//-- I cannot find a way to reliably throw an error, but keep it in case it does
|
|
661
|
+
/* istanbul ignore next */
|
|
662
|
+
return null;
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
module.exports.safeConvertBoolean = function safeConvertBoolean(val) {
|
|
667
|
+
if (typeof val === 'string') {
|
|
668
|
+
return val.toUpperCase() === 'TRUE';
|
|
669
|
+
}
|
|
670
|
+
return val ? true : false;
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
module.exports.prepareFormatterObject = function prepareFormatterObject(formatterObject) {
|
|
674
|
+
//-- @TODO: find way to reliably say that the propertyTranslation is an object
|
|
675
|
+
// propertyTranslations.constructor.name !== 'Object'
|
|
676
|
+
if (!formatterObject) {
|
|
677
|
+
throw Error(['ObjectUtils.formatProperties(collection, propertyTranslations): propertyTranslations must be an object, ',
|
|
678
|
+
'with the properties matching those to be formatted, and values as functions returning the new value'].join(''));
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const translationKeys = Array.from(Object.keys(formatterObject));
|
|
682
|
+
|
|
683
|
+
const result = ({ ...formatterObject });
|
|
684
|
+
|
|
685
|
+
translationKeys.forEach((key) => {
|
|
686
|
+
const translationVal = formatterObject[key];
|
|
687
|
+
if (typeof translationVal === 'function') {
|
|
688
|
+
//-- do nothing
|
|
689
|
+
} else if (translationVal === 'string') {
|
|
690
|
+
result[key] = FormatUtils.safeConvertString;
|
|
691
|
+
} else if (translationVal === 'number' || translationVal === 'float') {
|
|
692
|
+
result[key] = FormatUtils.safeConvertFloat;
|
|
693
|
+
} else if (translationVal === 'int' || translationVal === 'integer') {
|
|
694
|
+
result[key] = FormatUtils.safeConvertInteger;
|
|
695
|
+
} else if (translationVal === 'boolean') {
|
|
696
|
+
result[key] = FormatUtils.safeConvertBoolean;
|
|
697
|
+
} else {
|
|
698
|
+
result[key] = () => translationVal;
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
return result;
|
|
703
|
+
};
|
package/src/object.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const schemaGenerator = require('generate-schema');
|
|
4
4
|
|
|
5
|
+
const FormatUtils = require('./format');
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Utility for working with and massaging javascript objects.
|
|
7
9
|
*
|
|
@@ -18,6 +20,7 @@ const schemaGenerator = require('generate-schema');
|
|
|
18
20
|
* * {@link module:object.selectObjectProperties|selectObjectProperties()} - keep only specific properties
|
|
19
21
|
* * {@link module:object.filterObjectProperties|filterObjectProperties()} - remove specific properties
|
|
20
22
|
* * {@link module:object.mapProperties|mapProperties(collection, fn, ...properties)} - map multiple properties at once (like parseInt, or toString)
|
|
23
|
+
* * {@link module:object.formatProperties|formatProperties(collection, propertyTranslation)} - map specific properties (ex: toString, toNumber, etc)
|
|
21
24
|
* * Fetch child properties from related objects
|
|
22
25
|
* * {@link module:object.fetchObjectProperty|fetchObjectProperty(object, string)} - use dot notation to bring a child property onto a parent
|
|
23
26
|
* * {@link module:object.fetchObjectProperties|fetchObjectProperties(object, string[])} - use dot notation to bring multiple child properties onto a parent
|
|
@@ -146,7 +149,8 @@ module.exports.objAssignEntities = function objAssignEntities(obj, entities) {
|
|
|
146
149
|
* Runs a map over a collection, and adds properties the the objects.
|
|
147
150
|
*
|
|
148
151
|
* @param {Object | Array<Object>} objCollection - object or collection of objects to augment
|
|
149
|
-
* @param {Function} mappingFn - (record) => {Object} mapping function
|
|
152
|
+
* @param {Function | Object} mappingFn - (record) => {Object} mapping function <br />
|
|
153
|
+
* or object with properties to create
|
|
150
154
|
* @param {Boolean} [inPlace=false] - whether to update the collection in place (true) or cloned (false)
|
|
151
155
|
* @returns {Array<Object>} - collection of records with the fields merged
|
|
152
156
|
* @example
|
|
@@ -439,6 +443,82 @@ module.exports.fetchObjectProperty = function fetchObjectProperty(obj, propertyA
|
|
|
439
443
|
}, obj);
|
|
440
444
|
};
|
|
441
445
|
|
|
446
|
+
/**
|
|
447
|
+
* Translates specific properties to a new value on an object, or collection of objects.
|
|
448
|
+
*
|
|
449
|
+
* The properties defined in the `propertyTranslations` argument is then the property to be updated. (All other properties remain the same)
|
|
450
|
+
*
|
|
451
|
+
* You can either provide a function accepting the current value and returning the new value (any) => any
|
|
452
|
+
*
|
|
453
|
+
* Or you can provide one of the common shorthands:
|
|
454
|
+
*
|
|
455
|
+
* * 'string'
|
|
456
|
+
* * 'float' or 'number'
|
|
457
|
+
* * 'int' or 'integer'
|
|
458
|
+
* * 'boolean'
|
|
459
|
+
*
|
|
460
|
+
* ```
|
|
461
|
+
* data = [
|
|
462
|
+
* {station: 'A', isFahreinheit: 'true', offset: '0', temp: 98, type: 'F', descr: '0123'},
|
|
463
|
+
* {station: 'A', isFahreinheit: 'TRUE', offset: '2', temp: 99, type: 'F', descr: '0123456'},
|
|
464
|
+
* {station: 'A', isFahreinheit: 'false', offset: '3', temp: 100, type: 'F', descr: '0123456789'}
|
|
465
|
+
* ];
|
|
466
|
+
*
|
|
467
|
+
* utils.object.format(data, ({
|
|
468
|
+
* //-- to a literal value
|
|
469
|
+
* type: 'C',
|
|
470
|
+
* //-- convert it to 'string', 'number' || 'float', 'int' || 'integer', 'boolean'
|
|
471
|
+
* offset: 'number',
|
|
472
|
+
* isFahreinheit: 'boolean',
|
|
473
|
+
* //-- or convert the value with a function accepting the current value
|
|
474
|
+
* //-- and returning the new value
|
|
475
|
+
* temp: (val) => (val - 32) * 0.5556
|
|
476
|
+
* }));
|
|
477
|
+
*
|
|
478
|
+
* // [
|
|
479
|
+
* // { station: 'A', isFahreinheit: true, offset: 0, temp: 36.669599999999996, type: 'C', descr: '0123' },
|
|
480
|
+
* // { station: 'A', isFahreinheit: true, offset: 2, temp: 37.2252, type: 'C', descr: '0123456' },
|
|
481
|
+
* // { station: 'A', isFahreinheit: false, offset: 3, temp: 37.7808, type: 'C', descr: '0123456789' }
|
|
482
|
+
* // ];
|
|
483
|
+
* ```
|
|
484
|
+
*
|
|
485
|
+
* **Please note, you can pass a single object to be cleaned**,<br /> but it will be returned as an array of one object.
|
|
486
|
+
*
|
|
487
|
+
* ```
|
|
488
|
+
* data = [{station: 'A', isFahreinheit: 'TRUE', offset: '2', temp: 99, type: 'F', descr: '0123456'}];
|
|
489
|
+
*
|
|
490
|
+
* utils.object.format(data, ({
|
|
491
|
+
* //-- convert it to 'string', 'number' || 'float', 'int' || 'integer', 'boolean'
|
|
492
|
+
* offset: 'number',
|
|
493
|
+
* isFahreinheit: 'boolean'
|
|
494
|
+
* }));
|
|
495
|
+
*
|
|
496
|
+
* // [{station: 'A', isFahreinheit: true, offset: 2, temp: 99, type: 'F', descr: '0123456'}];
|
|
497
|
+
* ```
|
|
498
|
+
*
|
|
499
|
+
* @param {Object} collection - the list of objects to update specific properties
|
|
500
|
+
* @param {Object} propertyTranslations - An object with property names as the properties to update <br />
|
|
501
|
+
* and the values as a function ((any) => any) accepting the current value, returning the new value.
|
|
502
|
+
* @returns {Object[]} - collection of objects transformed
|
|
503
|
+
* @see {@link module:object.augment|augment(collection, fn)} - to add in new properties
|
|
504
|
+
* @see {@link TableGenerator#formatter} - for other examples
|
|
505
|
+
*/
|
|
506
|
+
module.exports.formatProperties = function formatProperties(collection, propertyTranslations) {
|
|
507
|
+
const cleanCollection = !collection ? []
|
|
508
|
+
: Array.isArray(collection) ? collection : [collection];
|
|
509
|
+
|
|
510
|
+
propertyTranslations = FormatUtils.prepareFormatterObject(propertyTranslations);
|
|
511
|
+
const translationKeys = Array.from(Object.keys(propertyTranslations));
|
|
512
|
+
|
|
513
|
+
return cleanCollection.map((obj) => {
|
|
514
|
+
const clone = { ...obj };
|
|
515
|
+
translationKeys.forEach((key) => {
|
|
516
|
+
clone[key] = propertyTranslations[key](clone[key]);
|
|
517
|
+
});
|
|
518
|
+
return clone;
|
|
519
|
+
});
|
|
520
|
+
};
|
|
521
|
+
|
|
442
522
|
/**
|
|
443
523
|
* returns a map of the types of fields stored
|
|
444
524
|
* @see generateSchema
|