@flourish/sdk 5.2.6 → 5.2.7
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/RELEASE_NOTES.md +3 -0
- package/package.json +1 -1
- package/server/index.js +1 -1
- package/site/script.js +2 -2
- package/site/sdk.css +2 -2
- package/server/columns.js +0 -201
- package/server/data.js +0 -327
- package/server/json.js +0 -66
package/server/columns.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
2
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
3
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * */
|
|
4
|
-
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
8
|
-
|
|
9
|
-
const MAX_INTEGER = Math.pow(2, 31) - 1;
|
|
10
|
-
const MAX_RANGE_LENGTH = Math.pow(2, 15);
|
|
11
|
-
|
|
12
|
-
// Attempt to parse col_spec as a columns spec;
|
|
13
|
-
// return true if we succeed, and false if not.
|
|
14
|
-
function looksLikeMultipleColumns(col_spec) {
|
|
15
|
-
try {
|
|
16
|
-
parseColumns(col_spec);
|
|
17
|
-
}
|
|
18
|
-
catch (e) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
return true;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function parseColumn(col_spec, is_optional) {
|
|
25
|
-
col_spec = col_spec.toUpperCase();
|
|
26
|
-
if (!/^[A-Z]+$/.test(col_spec)) {
|
|
27
|
-
if (!col_spec) {
|
|
28
|
-
if (is_optional) return -1; // Use -1 for unassigned optional binding
|
|
29
|
-
else throw new Error("Non-optional data binding must specify column");
|
|
30
|
-
}
|
|
31
|
-
if (looksLikeMultipleColumns(col_spec)) {
|
|
32
|
-
throw new Error("You can only select one column");
|
|
33
|
-
}
|
|
34
|
-
else throw new Error("Invalid column specification: " + col_spec);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
var col_ix = 0;
|
|
38
|
-
for (var i = 0; i < col_spec.length; i++) {
|
|
39
|
-
col_ix = col_ix * 26 + (col_spec.charCodeAt(i) - 64);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (col_ix - 1 > MAX_INTEGER) console.warn("Column index out of range");
|
|
43
|
-
return Math.min(col_ix - 1, MAX_INTEGER);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function printColumn(col_ix) {
|
|
47
|
-
col_ix += 1;
|
|
48
|
-
var col_spec = "";
|
|
49
|
-
while (col_ix > 0) {
|
|
50
|
-
var q = Math.floor(col_ix / 26),
|
|
51
|
-
r = col_ix % 26;
|
|
52
|
-
|
|
53
|
-
if (r == 0) {
|
|
54
|
-
q -= 1;
|
|
55
|
-
r += 26;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
col_spec = String.fromCharCode(64 + r) + col_spec;
|
|
59
|
-
col_ix = q;
|
|
60
|
-
}
|
|
61
|
-
return col_spec;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function parseRange(col_range) {
|
|
65
|
-
var dash_mo = col_range.match(/\s*(?:[-–—:]|\.\.)\s*/);
|
|
66
|
-
if (!dash_mo) throw new Error("Failed to parse column range: " + col_range);
|
|
67
|
-
|
|
68
|
-
var first = col_range.substr(0, dash_mo.index),
|
|
69
|
-
last = col_range.substr(dash_mo.index + dash_mo[0].length);
|
|
70
|
-
|
|
71
|
-
var first_ix = parseColumn(first),
|
|
72
|
-
last_ix = parseColumn(last);
|
|
73
|
-
|
|
74
|
-
var r = [];
|
|
75
|
-
var incrementer = last_ix >= first_ix ? 1 : -1;
|
|
76
|
-
var n = Math.abs(last_ix - first_ix) + 1;
|
|
77
|
-
|
|
78
|
-
if (n > MAX_RANGE_LENGTH) {
|
|
79
|
-
console.warn("Truncating excessively long range");
|
|
80
|
-
n = MAX_RANGE_LENGTH;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
for (var i = 0; i < n; i++) {
|
|
84
|
-
r.push(first_ix + i*incrementer);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return r;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function printRange(start, end) {
|
|
91
|
-
return printColumn(start) + "-" + printColumn(end);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function parseColumns(cols_spec) {
|
|
95
|
-
var indexes = [];
|
|
96
|
-
|
|
97
|
-
cols_spec = cols_spec.replace(/^\s+|\s+$/g, "");
|
|
98
|
-
var split_cols = cols_spec.split(/\s*,\s*/);
|
|
99
|
-
if (split_cols.length == 1 && split_cols[0] === "") split_cols = [];
|
|
100
|
-
|
|
101
|
-
for (var i = 0; i < split_cols.length; i++) {
|
|
102
|
-
var col_or_range = split_cols[i];
|
|
103
|
-
if (/^[A-Za-z]+$/.test(col_or_range)) {
|
|
104
|
-
indexes.push(parseColumn(col_or_range));
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
Array.prototype.push.apply(indexes, parseRange(col_or_range));
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return indexes;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function splitIntoRanges(indexes) {
|
|
115
|
-
if (!indexes.length) {
|
|
116
|
-
return [];
|
|
117
|
-
}
|
|
118
|
-
var ranges = [];
|
|
119
|
-
var start = indexes[0], end = indexes[0];
|
|
120
|
-
var direction = null;
|
|
121
|
-
for (var i = 0; i < indexes.length - 1; i++) {
|
|
122
|
-
var diff = indexes[i + 1] - indexes[i];
|
|
123
|
-
if (direction === null && Math.abs(diff) === 1) {
|
|
124
|
-
// It's a range with either ascending columns (direction=1), or descending
|
|
125
|
-
// columns (direction=-1)
|
|
126
|
-
end = indexes[i + 1];
|
|
127
|
-
direction = diff;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (diff === direction) {
|
|
132
|
-
// The range is continuing in the same direction as before
|
|
133
|
-
end = indexes[i + 1];
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// There's nothing more in the range, so add it, and start a new range from the
|
|
138
|
-
// next column
|
|
139
|
-
ranges.push([start, end]);
|
|
140
|
-
start = end = indexes[i + 1];
|
|
141
|
-
direction = null;
|
|
142
|
-
}
|
|
143
|
-
// There will always be a range which hasn't been added at the end
|
|
144
|
-
ranges.push([start, end]);
|
|
145
|
-
return ranges;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function printColumns(indexes) {
|
|
149
|
-
var ranges = splitIntoRanges(indexes);
|
|
150
|
-
|
|
151
|
-
var r = [];
|
|
152
|
-
for (var i = 0; i < ranges.length; i++) {
|
|
153
|
-
var range = ranges[i];
|
|
154
|
-
if (range[0] == range[1]) r.push(printColumn(range[0]));
|
|
155
|
-
else r.push(printRange(range[0], range[1]));
|
|
156
|
-
}
|
|
157
|
-
return r.join(",");
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function parseDataBinding(d, data_table_ids) {
|
|
161
|
-
var r = {};
|
|
162
|
-
|
|
163
|
-
if (!(d.type in d)) {
|
|
164
|
-
if (d.optional) return r;
|
|
165
|
-
throw new Error("Data binding must specify '" + d.type + "': " + JSON.stringify(d));
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
var double_colon_ix = d[d.type].indexOf("::");
|
|
169
|
-
if (double_colon_ix == -1) throw new Error("Invalid data binding: " + d[d.type]);
|
|
170
|
-
var data_table_name = d[d.type].substr(0, double_colon_ix);
|
|
171
|
-
r.data_table_id = data_table_ids[data_table_name];
|
|
172
|
-
|
|
173
|
-
var col_spec = d[d.type].substr(double_colon_ix + 2);
|
|
174
|
-
if (d.type == "column") r.column = parseColumn(col_spec, d.optional);
|
|
175
|
-
else if (d.type == "columns") r.columns = parseColumns(col_spec);
|
|
176
|
-
else throw new Error("Unknown data binding type: " + d.type);
|
|
177
|
-
|
|
178
|
-
return r;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function printDataBinding(r, data_table_names, print_data_table_name, optional) {
|
|
182
|
-
var data_table_name = print_data_table_name ? data_table_names[r.data_table_id] + "::" : "";
|
|
183
|
-
if ("column" in r) {
|
|
184
|
-
return data_table_name + printColumn(r.column);
|
|
185
|
-
}
|
|
186
|
-
else if ("columns" in r) {
|
|
187
|
-
return data_table_name + printColumns(r.columns);
|
|
188
|
-
}
|
|
189
|
-
else if (optional) {
|
|
190
|
-
return "";
|
|
191
|
-
}
|
|
192
|
-
throw new Error("Data binding must have .column or .columns");
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
exports.parseColumn = parseColumn;
|
|
196
|
-
exports.parseColumns = parseColumns;
|
|
197
|
-
exports.parseDataBinding = parseDataBinding;
|
|
198
|
-
exports.parseRange = parseRange;
|
|
199
|
-
exports.printColumn = printColumn;
|
|
200
|
-
exports.printColumns = printColumns;
|
|
201
|
-
exports.printDataBinding = printDataBinding;
|
package/server/data.js
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
/* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
2
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
3
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * */
|
|
4
|
-
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
8
|
-
|
|
9
|
-
var interpreter$1 = require('@flourish/interpreter');
|
|
10
|
-
|
|
11
|
-
// Polyfills for IE11 and Edge
|
|
12
|
-
|
|
13
|
-
// Add findIndex method to Array
|
|
14
|
-
// https://tc39.github.io/ecma262/#sec-array.prototype.findindex
|
|
15
|
-
if (!Array.prototype.findIndex) {
|
|
16
|
-
Object.defineProperty(Array.prototype, "findIndex", {
|
|
17
|
-
value: function(predicate) {
|
|
18
|
-
if (this == null) {
|
|
19
|
-
throw new TypeError("this is null or not defined");
|
|
20
|
-
}
|
|
21
|
-
var o = Object(this);
|
|
22
|
-
var len = o.length >>> 0;
|
|
23
|
-
if (typeof predicate !== "function") {
|
|
24
|
-
throw new TypeError("predicate must be a function");
|
|
25
|
-
}
|
|
26
|
-
var this_arg = arguments[1];
|
|
27
|
-
var k = 0;
|
|
28
|
-
while (k < len) {
|
|
29
|
-
var k_value = o[k];
|
|
30
|
-
if (predicate.call(this_arg, k_value, k, o)) {
|
|
31
|
-
return k;
|
|
32
|
-
}
|
|
33
|
-
k++;
|
|
34
|
-
}
|
|
35
|
-
return -1;
|
|
36
|
-
},
|
|
37
|
-
configurable: true,
|
|
38
|
-
writable: true
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function extractData(data_binding, data_by_id, column_types_by_id, template_data_binding) {
|
|
43
|
-
var columns = [];
|
|
44
|
-
var data_table_ids = [];
|
|
45
|
-
var num_rows = 0;
|
|
46
|
-
var dataset = [];
|
|
47
|
-
var interpreters_by_id = {};
|
|
48
|
-
dataset.column_names = {};
|
|
49
|
-
dataset.metadata = {};
|
|
50
|
-
|
|
51
|
-
function getInterpretationIds(data_table_id, column_index) {
|
|
52
|
-
if (!interpreters_by_id[data_table_id]) return {};
|
|
53
|
-
var by_column_index = interpreters_by_id[data_table_id];
|
|
54
|
-
if (!by_column_index[column_index]) return {};
|
|
55
|
-
return by_column_index[column_index];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function getInterpreter(data_table_id, column_index) {
|
|
59
|
-
const { type_id } = getInterpretationIds(data_table_id, column_index);
|
|
60
|
-
if (type_id) return interpreter$1.createInterpreter.getInterpretation(type_id);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
for (var data_table_id in column_types_by_id) {
|
|
64
|
-
var lookup = {};
|
|
65
|
-
var column_types = column_types_by_id[data_table_id];
|
|
66
|
-
if (!column_types) continue;
|
|
67
|
-
|
|
68
|
-
for (let i = 0; i < column_types.length; i++) {
|
|
69
|
-
const type_id = column_types[i].type_id;
|
|
70
|
-
const of_id = column_types[i].output_format_id;
|
|
71
|
-
const output_format_id = (!of_id || of_id === "auto") ? type_id : of_id;
|
|
72
|
-
lookup[column_types[i].index] = { type_id, output_format_id };
|
|
73
|
-
}
|
|
74
|
-
interpreters_by_id[data_table_id] = lookup;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
for (var key in data_binding) {
|
|
78
|
-
if (data_binding[key] === null) continue;
|
|
79
|
-
if (data_binding[key].columns === undefined && data_binding[key].column === undefined) continue;
|
|
80
|
-
|
|
81
|
-
var b = data_binding[key];
|
|
82
|
-
b.template_data_binding = template_data_binding[key];
|
|
83
|
-
b.key = key;
|
|
84
|
-
|
|
85
|
-
if (!(b.data_table_id in data_by_id)) {
|
|
86
|
-
var data_by_id_keys = [];
|
|
87
|
-
for (var k in data_by_id) data_by_id_keys.push(k);
|
|
88
|
-
|
|
89
|
-
console.error("Data table id " + b.data_table_id + " not in " + JSON.stringify(data_by_id_keys));
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
var data_table = data_by_id[b.data_table_id];
|
|
94
|
-
if (data_table.length == 0) {
|
|
95
|
-
console.warn("Empty data table");
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if ("columns" in b && b.columns != null) {
|
|
100
|
-
var column_count = data_table[0].length;
|
|
101
|
-
b.columns = b.columns.filter(function(i) { return i < column_count; });
|
|
102
|
-
dataset.column_names[key] = b.columns.map(function(i) {
|
|
103
|
-
return data_table[0][i];
|
|
104
|
-
});
|
|
105
|
-
dataset.metadata[key] = b.columns.map(function(i) {
|
|
106
|
-
const { type_id, output_format_id } = getInterpretationIds(b.data_table_id, i);
|
|
107
|
-
if (type_id) {
|
|
108
|
-
return {
|
|
109
|
-
type: type_id.split("$")[0],
|
|
110
|
-
type_id,
|
|
111
|
-
output_format_id: output_format_id
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
else if ("column" in b && b.column != null) {
|
|
118
|
-
dataset.column_names[key] = data_table[0][b.column];
|
|
119
|
-
const { type_id, output_format_id } = getInterpretationIds(b.data_table_id, b.column);
|
|
120
|
-
if (type_id) {
|
|
121
|
-
dataset.metadata[key] = {
|
|
122
|
-
type: type_id.split("$")[0],
|
|
123
|
-
type_id,
|
|
124
|
-
output_format_id: output_format_id
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
throw new Error("Data binding includes no column(s) specification: " + JSON.stringify(b));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (data_table_ids.indexOf(b.data_table_id) == -1) {
|
|
133
|
-
data_table_ids.push(b.data_table_id);
|
|
134
|
-
num_rows = Math.max(num_rows, data_table.length - 1);
|
|
135
|
-
}
|
|
136
|
-
columns.push(b);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function parse(b, column_index, string_value) {
|
|
140
|
-
if (!b.template_data_binding.data_type) return string_value;
|
|
141
|
-
var interpreter = getInterpreter(b.data_table_id, column_index);
|
|
142
|
-
if (interpreter && interpreter.type == "number") string_value = stripCommonFixes(string_value);
|
|
143
|
-
var result = interpreter ? interpreter.parse(string_value) : string_value;
|
|
144
|
-
|
|
145
|
-
// We require our marshalled data to be JSON-serialisable,
|
|
146
|
-
// therefore we convert NaNs to null here.
|
|
147
|
-
if (Number.isNaN(result)) result = null;
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
for (var i = 0; i < num_rows; i++) {
|
|
152
|
-
var o = {};
|
|
153
|
-
for (var j = 0; j < columns.length; j++) {
|
|
154
|
-
b = columns[j];
|
|
155
|
-
var table = data_by_id[b.data_table_id];
|
|
156
|
-
if (i+1 >= table.length) continue;
|
|
157
|
-
|
|
158
|
-
if ("columns" in b && b.columns != null) {
|
|
159
|
-
o[b.key] = b.columns
|
|
160
|
-
.filter(function(c) { return c < table[i+1].length; })
|
|
161
|
-
.map(function(c) { return parse(b, c, table[i+1][c]); });
|
|
162
|
-
}
|
|
163
|
-
else if ("column" in b && b.column != null) {
|
|
164
|
-
if (b.column >= table[i+1].length) o[b.key] = parse(b, b.column, "");
|
|
165
|
-
else o[b.key] = parse(b, b.column, table[i+1][b.column]);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
dataset.push(o);
|
|
169
|
-
}
|
|
170
|
-
return dataset;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function getColumnTypesForData(data) {
|
|
174
|
-
return transposeNestedArray(data)
|
|
175
|
-
.map(function(column, i) {
|
|
176
|
-
const sliced_column = getSlicedData(column);
|
|
177
|
-
const sample_size = 1000;
|
|
178
|
-
let sample_data;
|
|
179
|
-
if (sliced_column.length > (sample_size * 2)) sample_data = getRandomSeededSample(sliced_column, sample_size);
|
|
180
|
-
else sample_data = sliced_column;
|
|
181
|
-
const type_id = interpretColumn(sample_data)[0].id;
|
|
182
|
-
return { type_id: type_id, index: i, output_format_id: type_id };
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Returns a random seeded sample of column values based on the column length.
|
|
187
|
-
// The sample is consistent and will update if the length of column changes.
|
|
188
|
-
function getRandomSeededSample(column, sample_size) {
|
|
189
|
-
if (column.length <= sample_size * 2) return column;
|
|
190
|
-
const rng = mulberry32(column.length);
|
|
191
|
-
|
|
192
|
-
while (column.length > sample_size) {
|
|
193
|
-
const random_index = Math.floor(rng() * column.length);
|
|
194
|
-
|
|
195
|
-
column.splice(random_index, 1);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return column;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Seeded RNG implementation taken from https://github.com/bryc/code/blob/master/jshash/PRNGs.md#mulberry32
|
|
202
|
-
function mulberry32(seed) {
|
|
203
|
-
let a = seed;
|
|
204
|
-
return function() {
|
|
205
|
-
a |= 0; a = a + 0x6D2B79F5 | 0;
|
|
206
|
-
var t = Math.imul(a ^ a >>> 15, 1 | a);
|
|
207
|
-
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
208
|
-
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function trimTrailingEmptyRows(data) {
|
|
213
|
-
for (var i = data.length; i-- > 1;) {
|
|
214
|
-
if (!data[i] || !data[i].length || (Array.isArray(data[i]) && data[i].findIndex(function(col) { return col !== null && col !== ""; }) == -1)) {
|
|
215
|
-
data.splice(i, 1);
|
|
216
|
-
}
|
|
217
|
-
else break;
|
|
218
|
-
}
|
|
219
|
-
return data;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function dropReturnCharacters(data) {
|
|
223
|
-
for (const row of data) {
|
|
224
|
-
for (let i = 0; i < row.length; i++) {
|
|
225
|
-
// Due to a bug in HoT, pasting long lines from Excel can lead to the addition of
|
|
226
|
-
// a newline character and a space *before* a space character.
|
|
227
|
-
// This leads to a pattern of new line character followed by two spaces.
|
|
228
|
-
// Here we identify that pattern and revert it.
|
|
229
|
-
row[i] = row[i].replace(/(\r\n|\n|\r) {2}/g, " ");
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
return data;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Takes an array of arrays (typically tabular data) and rewrites
|
|
237
|
-
* it so that:
|
|
238
|
-
* - Any trailing empty rows are removed
|
|
239
|
-
* - Any cell that was not a string is stringified
|
|
240
|
-
* - Any leading or trailing whitespace of a cell is removed
|
|
241
|
-
*
|
|
242
|
-
* (The potentially modified table is returned to match the convention
|
|
243
|
-
* used by functions this is replacing, although (TODO) I think it
|
|
244
|
-
* would be more obvious that this function has side-effects if it
|
|
245
|
-
* did not return the table and the calling code was changed.)
|
|
246
|
-
*
|
|
247
|
-
* @param {any[][]} data
|
|
248
|
-
* @returns {string[][]}
|
|
249
|
-
*/
|
|
250
|
-
function tidyTable(data) {
|
|
251
|
-
trimTrailingEmptyRows(data);
|
|
252
|
-
for (let row of data) {
|
|
253
|
-
for (let i = 0; i < row.length; i++) {
|
|
254
|
-
let value = row[i];
|
|
255
|
-
// Convert null or undefined values to the empty string
|
|
256
|
-
if (value == null) value = "";
|
|
257
|
-
// If the value is not a string, convert it to one
|
|
258
|
-
if (typeof value !== "string") {
|
|
259
|
-
value = "" + value;
|
|
260
|
-
}
|
|
261
|
-
// Now value is a definitely a string, strip any leading
|
|
262
|
-
// or trailing whitespace.
|
|
263
|
-
row[i] = value.trim();
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
return data;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
var ERROR_STRINGS = ["#DIV/0", "#N/A", "#NAME?", "#NULL!", "#NUM!", "#REF!", "#VALUE!", "#ERROR!"];
|
|
271
|
-
var interpreter = interpreter$1.createInterpreter().nMax(Infinity).nFailingValues(8).failureFraction(0.1);
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
function stripCommonFixes(str) {
|
|
275
|
-
str = str || "";
|
|
276
|
-
return str.replace(/[€£$¥%º]/g, "");
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
function transposeNestedArray(nested_array) {
|
|
281
|
-
var n_inner = nested_array.length;
|
|
282
|
-
var n_outer = n_inner > 0 ? nested_array[0].length : 0;
|
|
283
|
-
var transposed_array = [];
|
|
284
|
-
|
|
285
|
-
for (var i = 0; i < n_outer; i++) {
|
|
286
|
-
var data = [];
|
|
287
|
-
for (var j = 0; j < n_inner; j++) {
|
|
288
|
-
data.push(nested_array[j][i]);
|
|
289
|
-
}
|
|
290
|
-
transposed_array.push(data);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return transposed_array;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
function getSlicedData(arr) {
|
|
298
|
-
const n = arr.length;
|
|
299
|
-
if (n > 100) return arr.slice(10, n - 10);
|
|
300
|
-
if (n > 50) return arr.slice(5, n - 5);
|
|
301
|
-
if (n > 30) return arr.slice(4, n - 4);
|
|
302
|
-
if (n > 20) return arr.slice(3, n - 3);
|
|
303
|
-
if (n > 10) return arr.slice(2, n - 2);
|
|
304
|
-
if (n > 1) return arr.slice(1, n);
|
|
305
|
-
return arr.slice(0, 1);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
function interpretColumn(arr) {
|
|
310
|
-
var idata = arr.filter(function(d) {
|
|
311
|
-
return d && !ERROR_STRINGS.includes(d.trim());
|
|
312
|
-
})
|
|
313
|
-
.map(stripCommonFixes);
|
|
314
|
-
return interpreter(idata);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
exports.dropReturnCharacters = dropReturnCharacters;
|
|
318
|
-
exports.extractData = extractData;
|
|
319
|
-
exports.getColumnTypesForData = getColumnTypesForData;
|
|
320
|
-
exports.getRandomSeededSample = getRandomSeededSample;
|
|
321
|
-
exports.getSlicedData = getSlicedData;
|
|
322
|
-
exports.interpretColumn = interpretColumn;
|
|
323
|
-
exports.mulberry32 = mulberry32;
|
|
324
|
-
exports.stripCommonFixes = stripCommonFixes;
|
|
325
|
-
exports.tidyTable = tidyTable;
|
|
326
|
-
exports.transposeNestedArray = transposeNestedArray;
|
|
327
|
-
exports.trimTrailingEmptyRows = trimTrailingEmptyRows;
|
package/server/json.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
2
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * *
|
|
3
|
-
* * * * * * GENERATED FILE - DO NOT EDIT * * * * * */
|
|
4
|
-
|
|
5
|
-
'use strict';
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
8
|
-
|
|
9
|
-
function escapeChar(c) {
|
|
10
|
-
var hex = c.charCodeAt(0).toString(16);
|
|
11
|
-
while (hex.length < 4) hex = "0" + hex;
|
|
12
|
-
return "\\u" + hex;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Stringify an object (etc.) in a form that can safely be inserted
|
|
16
|
-
// into a <script> block in a web page.
|
|
17
|
-
function safeStringify(obj) {
|
|
18
|
-
const raw = JSON.stringify(obj);
|
|
19
|
-
if (typeof raw === "undefined") return undefined;
|
|
20
|
-
return raw.replace(/[\u2028\u2029<]/g, escapeChar);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function javaScriptStringify(v) {
|
|
24
|
-
var type = typeof v;
|
|
25
|
-
if (v == null) {
|
|
26
|
-
// Catches both null and undefined
|
|
27
|
-
return "null";
|
|
28
|
-
}
|
|
29
|
-
else if (type === "number" || type === "boolean" || type === "bigint" || type === "string" || type === "symbol") {
|
|
30
|
-
return safeStringify(v);
|
|
31
|
-
}
|
|
32
|
-
if (Array.isArray(v)) {
|
|
33
|
-
return "[" + v.map(javaScriptStringify).join(",") + "]";
|
|
34
|
-
}
|
|
35
|
-
else if (v instanceof Date) {
|
|
36
|
-
return "new Date(" + v.getTime() + ")";
|
|
37
|
-
}
|
|
38
|
-
else if (Object.prototype.toString.call(v) === "[object Object]") {
|
|
39
|
-
return "{" + Object.keys(v).map(function (k) {
|
|
40
|
-
return safeStringify(k) + ":" + javaScriptStringify(v[k]);
|
|
41
|
-
}) + "}";
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
throw new Error("javaScriptStringify couldn't handle " + type + " object: " + v);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function stringifyDataset(dataset) {
|
|
49
|
-
return "(function(array, column_names, metadata){ array.column_names = column_names; array.metadata = metadata; return array; })(" + javaScriptStringify(dataset) + ", " + safeStringify(dataset.column_names) + ", " + safeStringify(dataset.metadata) + ")";
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function stringifyPreparedData(data) {
|
|
53
|
-
var s = "{";
|
|
54
|
-
var first = true;
|
|
55
|
-
for (var dataset in data) {
|
|
56
|
-
if (first) first = false; else s += ", ";
|
|
57
|
-
s += safeStringify(dataset) + ": " + stringifyDataset(data[dataset]);
|
|
58
|
-
}
|
|
59
|
-
s += "}";
|
|
60
|
-
|
|
61
|
-
return s;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
exports.javaScriptStringify = javaScriptStringify;
|
|
65
|
-
exports.safeStringify = safeStringify;
|
|
66
|
-
exports.stringifyPreparedData = stringifyPreparedData;
|