jupyter-ijavascript-utils 1.30.0 → 1.31.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 CHANGED
@@ -75,6 +75,7 @@ Give it a try here:
75
75
 
76
76
  ## What's New
77
77
 
78
+ * 1.31 - harden Array.transpose for arrays with nulls, and Table.generateTSV
78
79
  * 1.30 - add Format.wordWrap and Format.lineCount
79
80
  * 1.29 - Updated TableGenerator.format method
80
81
  * 1.28 - Sticky table headers for table.render
package/Dockerfile CHANGED
@@ -1,3 +1,3 @@
1
1
  # syntax=docker/dockerfile:1
2
2
 
3
- FROM darkbluestudios/jupyter-ijavascript-utils:binder_1.30.0
3
+ FROM darkbluestudios/jupyter-ijavascript-utils:binder_1.31.0
package/README.md CHANGED
@@ -55,6 +55,7 @@ This is not intended to be the only way to accomplish many of these tasks, and a
55
55
 
56
56
  # What's New
57
57
 
58
+ * 1.31 - harden Array.transpose for arrays with nulls, and Table.generateTSV
58
59
  * 1.30 - add Format.wordWrap and Format.lineCount
59
60
  * 1.29 - Updated TableGenerator.format method
60
61
  * 1.28 - Sticky table headers for table.render
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jupyter-ijavascript-utils",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
4
4
  "description": "Utilities for working with iJavaScript - a Jupyter Kernel",
5
5
  "homepage": "https://jupyter-ijavascript-utils.onrender.com/",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "eslint-plugin-import": "^2.26.0",
41
41
  "eslint-watch": "^7.0.0",
42
42
  "jest": "^27.0.6",
43
- "jsdoc": "^3.6.10",
43
+ "jsdoc": "^4.0.2",
44
44
  "sinon": "^11.1.1"
45
45
  },
46
46
  "dependencies": {
@@ -135,10 +135,14 @@ const { createSort } = require('./array');
135
135
  * * {@link TableGenerator#generateHTML|generateHTML()} - returns html table with the results
136
136
  * * {@link TableGenerator#generateMarkdown|generateMarkdown()} - returns markdown with the results
137
137
  * * {@link TableGenerator#generateCSV|generateCSV()} - generates a CSV with the results
138
+ * * {@link TableGenerator#generateCSV|generateCSV()} - generates a TSV with the results
138
139
  * * {@link TableGenerator#generateArray|generateArray()} - generates an array of headers and data for further process
139
140
  * * {@link TableGenerator#generateArray2|generateArray2()} - generates a single array for further process
140
141
  * * render in jupyter
141
142
  * * {@link TableGenerator#render|render()} - renders the results in a table within jupyter
143
+ * * {@link TableGenerator#renderCSV|renderCSV()} - renders the generateCSV results in a table within jupyter
144
+ * * {@link TableGenerator#renderTSV|renderTSV()} - renders the generateTSV results in a table within jupyter
145
+ * * {@link TableGenerator#renderMarkdown|renderMarkdown()} - renders the generateMarkdown results in a table within jupyter
142
146
  *
143
147
  */
144
148
  class TableGenerator {
@@ -1398,6 +1402,43 @@ class TableGenerator {
1398
1402
  return tableResults;
1399
1403
  }
1400
1404
 
1405
+ /**
1406
+ * Generates a TSV Table
1407
+ * @see {@link TableGenerator#renderCSV}
1408
+ */
1409
+ generateTSV() {
1410
+ const results = this.prepare();
1411
+
1412
+ const printOptions = this.#printOptions;
1413
+
1414
+ const escapeString = (val) => {
1415
+ //-- always return as string values to preserve formatting
1416
+ return `"${
1417
+ printValue(val, printOptions)
1418
+ .replace(/"/g, '""')
1419
+ }"`;
1420
+ };
1421
+ const tsvify = (a) => a.map(escapeString)
1422
+ .join('\t');
1423
+
1424
+ const printHeader = (headers, style) => tsvify(headers)
1425
+ + '\n';
1426
+
1427
+ const printBody = (collection) => collection
1428
+ .map((dataRow) => tsvify(dataRow))
1429
+ .join('\n');
1430
+
1431
+ // const cleanFn = printValue;
1432
+ // .map((dataRow) => tsvify(dataRow.map((value) =>
1433
+ // cleanFn(value, printOptions))
1434
+ // )).join('\n');
1435
+
1436
+ const tableResults = printHeader(results.headers, '')
1437
+ + printBody(results.data);
1438
+
1439
+ return tableResults;
1440
+ }
1441
+
1401
1442
  /**
1402
1443
  * @typedef {Object} TableArray
1403
1444
  * @property {String} headers -
@@ -1601,6 +1642,44 @@ class TableGenerator {
1601
1642
 
1602
1643
  context.console.log(this.generateCSV());
1603
1644
  }
1645
+
1646
+ /**
1647
+ * Renders Markdown in the cell results
1648
+ * @see {@link TableGenerator#generateTSV}
1649
+ * @example
1650
+ * weather = [
1651
+ * { id: 1, city: 'Seattle', month: 'Aug', precip: 0.87 },
1652
+ * { id: 0, city: 'Seattle', month: 'Apr', precip: 2.68 },
1653
+ * { id: 2, city: 'Seattle', month: 'Dec', precip: 5.31 },
1654
+ * { id: 3, city: 'New York', month: 'Apr', precip: 3.94 },
1655
+ * { id: 4, city: 'New York', month: 'Aug', precip: 4.13 },
1656
+ * { id: 5, city: 'New York', month: 'Dec', precip: 3.58 },
1657
+ * { id: 6, city: 'Chicago', month: 'Apr', precip: 3.62 },
1658
+ * { id: 8, city: 'Chicago', month: 'Dec', precip: 2.56 },
1659
+ * { id: 7, city: 'Chicago', month: 'Aug', precip: 3.98 }
1660
+ * ];
1661
+ * utils.table(weather)
1662
+ * .renderTSV();
1663
+ *
1664
+ * // "id","city","month","precip"
1665
+ * // "1","Seattle","Aug","0.87"
1666
+ * // "0","Seattle","Apr","2.68"
1667
+ * // "2","Seattle","Dec","5.31"
1668
+ * // "3","New York","Apr","3.94"
1669
+ * // "4","New York","Aug","4.13"
1670
+ * // "5","New York","Dec","3.58"
1671
+ * // "6","Chicago","Apr","3.62"
1672
+ * // "8","Chicago","Dec","2.56"
1673
+ * // "7","Chicago","Aug","3.98"
1674
+ */
1675
+ renderTSV() {
1676
+ const context = IJSUtils.detectContext();
1677
+ if (!context) {
1678
+ throw (Error('Not in iJavaScript, no $$ variable available'));
1679
+ }
1680
+
1681
+ context.console.log(this.generateTSV());
1682
+ }
1604
1683
  }
1605
1684
 
1606
1685
  module.exports = TableGenerator;
package/src/array.js CHANGED
@@ -26,6 +26,8 @@ require('./_types/global');
26
26
  * * {@link module:array.pickRows|array.pickRows} - picks a row from a 2d array
27
27
  * * {@link module:array.pickColumns|array.pickColumns} - picks a column from a 2d array
28
28
  * * {@link module:array.pick|array.pick} - picks either/or rows and columns
29
+ * * Understanding Values
30
+ * * {@link module:array.isMultiDimensional|array.isMultiDimensional} - determines if an array is multi-dimensional
29
31
  *
30
32
  * @module array
31
33
  * @exports array
@@ -300,6 +302,42 @@ module.exports.arrange = function arange(len, start = 0, step = 1) {
300
302
  */
301
303
  module.exports.arange = module.exports.arrange;
302
304
 
305
+ /**
306
+ * Determine whether an array is multi-dimensional (an array of arrays)
307
+ *
308
+ * For example:
309
+ *
310
+ * ```
311
+ * utils.array.isMultiDimensional(0); // false
312
+ * utils.array.isMultiDimensional([0,1,2,3]); // false
313
+ * utils.array.isMultiDimensional([[0,1], [2,3]]); // true
314
+ * utils.array.isMultiDimensional([0, [1,2]]); // true
315
+ * ```
316
+ *
317
+ * @param {Array} targetArray - array to check if multi-dimensional
318
+ * @returns {Boolean} - if the targetArray has any values that are multi-dimensional
319
+ */
320
+ module.exports.isMultiDimensional = function isMultiDimensional(targetArray) {
321
+ if (!targetArray || !Array.isArray(targetArray)) {
322
+ return false;
323
+ }
324
+ return targetArray.find((v) => Array.isArray(v)) !== undefined;
325
+ };
326
+
327
+ /**
328
+ * Determines the depth of a two dimensional array
329
+ * @param {Array} targetArray - two dimensional array
330
+ * @returns {Number}
331
+ * @private
332
+ */
333
+ module.exports.arrayLength2d = function arrayLength2d(targetArray) {
334
+ return (targetArray || [])
335
+ .reduce((max, line) => {
336
+ const len = (line || []).length;
337
+ return (len > max) ? len : max;
338
+ }, 0);
339
+ };
340
+
303
341
  /**
304
342
  * Transposes a two dimensional array, so an NxM becomes MxN
305
343
  * @param {any[]} matrix - MxN array
@@ -329,7 +367,7 @@ module.exports.transpose = function transpose(matrix) {
329
367
 
330
368
  //-- for speed, we use for loops.
331
369
  const rows = matrix.length;
332
- const cols = matrix[0].length;
370
+ const cols = ArrayUtils.arrayLength2d(matrix); // matrix[0].length;
333
371
  let colI;
334
372
  let rowI;
335
373
 
@@ -466,5 +504,3 @@ module.exports.arrangeMulti = function arangeMulti(...dimensions) {
466
504
  return ArrayUtils.size(currentDimension, () => ArrayUtils.clone(childDimensionalValue));
467
505
  };
468
506
  module.exports.arangeMulti = module.exports.arrangeMulti;
469
-
470
- //-- collection utilities