sv 0.4.2 → 0.5.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/LICENSE +7 -0
- package/README.md +20 -128
- package/dist/bin.js +13085 -0
- package/dist/bin.js.map +1 -0
- package/dist/index-CfDBZLMZ.js +137 -0
- package/dist/index-CfDBZLMZ.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/shared.json +138 -0
- package/dist/templates/demo/assets/DOT-gitignore +21 -0
- package/dist/templates/demo/assets/DOT-npmrc +1 -0
- package/dist/templates/demo/assets/src/app.css +107 -0
- package/dist/templates/demo/assets/src/app.html +12 -0
- package/dist/templates/demo/assets/src/lib/images/github.svg +16 -0
- package/dist/templates/demo/assets/src/lib/images/svelte-logo.svg +1 -0
- package/dist/templates/demo/assets/src/lib/images/svelte-welcome.png +0 -0
- package/dist/templates/demo/assets/src/lib/images/svelte-welcome.webp +0 -0
- package/dist/templates/demo/assets/static/favicon.png +0 -0
- package/dist/templates/demo/assets/static/robots.txt +3 -0
- package/dist/templates/demo/files.types=checkjs.json +62 -0
- package/dist/templates/demo/files.types=none.json +58 -0
- package/dist/templates/demo/files.types=typescript.json +62 -0
- package/dist/templates/demo/meta.json +4 -0
- package/dist/templates/demo/package.json +19 -0
- package/dist/templates/skeleton/assets/DOT-gitignore +21 -0
- package/dist/templates/skeleton/assets/DOT-npmrc +1 -0
- package/dist/templates/skeleton/assets/src/app.html +12 -0
- package/dist/templates/skeleton/assets/static/favicon.png +0 -0
- package/dist/templates/skeleton/files.types=checkjs.json +14 -0
- package/dist/templates/skeleton/files.types=none.json +10 -0
- package/dist/templates/skeleton/files.types=typescript.json +14 -0
- package/dist/templates/skeleton/meta.json +4 -0
- package/dist/templates/skeleton/package.json +18 -0
- package/dist/templates/skeletonlib/assets/DOT-gitignore +22 -0
- package/dist/templates/skeletonlib/assets/DOT-npmrc +1 -0
- package/dist/templates/skeletonlib/assets/src/app.html +12 -0
- package/dist/templates/skeletonlib/assets/static/favicon.png +0 -0
- package/dist/templates/skeletonlib/files.types=checkjs.json +14 -0
- package/dist/templates/skeletonlib/files.types=none.json +10 -0
- package/dist/templates/skeletonlib/files.types=typescript.json +14 -0
- package/dist/templates/skeletonlib/meta.json +4 -0
- package/dist/templates/skeletonlib/package.json +34 -0
- package/dist/unocss-Dk7i15rK.js +11 -0
- package/dist/unocss-Dk7i15rK.js.map +1 -0
- package/dist/unplugin-icons-DkNLYvBs.js +11 -0
- package/dist/unplugin-icons-DkNLYvBs.js.map +1 -0
- package/package.json +39 -27
- package/.npmignore +0 -14
- package/bin/sv.d.ts +0 -1
- package/bin/sv.js +0 -124
- package/common.d.ts +0 -38
- package/common.js +0 -27
- package/docs/example.js +0 -57
- package/index.d.ts +0 -12
- package/index.js +0 -29
- package/parser.d.ts +0 -29
- package/parser.js +0 -194
- package/stringifier.d.ts +0 -42
- package/stringifier.js +0 -159
package/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var json_1 = require('streaming/json');
|
|
3
|
-
var property_1 = require('streaming/property');
|
|
4
|
-
var parser_1 = require('./parser');
|
|
5
|
-
exports.Parser = parser_1.Parser;
|
|
6
|
-
var stringifier_1 = require('./stringifier');
|
|
7
|
-
exports.Stringifier = stringifier_1.Stringifier;
|
|
8
|
-
function transform(input, parserConfig, stringifierConfig, callback) {
|
|
9
|
-
var transforms = [
|
|
10
|
-
parserConfig.json ? new json_1.Parser() : new parser_1.Parser(parserConfig),
|
|
11
|
-
];
|
|
12
|
-
if (stringifierConfig.omit) {
|
|
13
|
-
transforms.push(new property_1.Omitter(stringifierConfig.omit.split(/,/g)));
|
|
14
|
-
}
|
|
15
|
-
if (stringifierConfig.filter) {
|
|
16
|
-
transforms.push(new property_1.Picker(stringifierConfig.filter.split(/,/g)));
|
|
17
|
-
}
|
|
18
|
-
var stringifier = stringifierConfig.json ? new json_1.Stringifier() : new stringifier_1.Stringifier(stringifierConfig);
|
|
19
|
-
transforms.push(stringifier);
|
|
20
|
-
var output = transforms.reduce(function (outputStream, transform) { return outputStream.pipe(transform); }, input).pipe(process.stdout);
|
|
21
|
-
output.on('finish', callback);
|
|
22
|
-
output.on('error', function (error) {
|
|
23
|
-
// panic! (lets us quit faster, actually)
|
|
24
|
-
input.unpipe();
|
|
25
|
-
// output.unpipe();
|
|
26
|
-
callback(error);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
exports.transform = transform;
|
package/parser.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Transform } from 'stream';
|
|
2
|
-
import { Configuration } from './common';
|
|
3
|
-
export interface ParserConfiguration extends Configuration {
|
|
4
|
-
}
|
|
5
|
-
export declare const defaultParserConfiguration: ParserConfiguration;
|
|
6
|
-
/**
|
|
7
|
-
returns a single char code (a byte) denoting the inferred delimiter.
|
|
8
|
-
*/
|
|
9
|
-
export declare function inferDelimiter(buffer: Buffer): number;
|
|
10
|
-
/**
|
|
11
|
-
- `byteBuffer` is a buffer (of bytes) that have yet to be processed (and sent to output).
|
|
12
|
-
- `cellBuffer` is a list of strings that have yet to be processed (and sent to output).
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
export declare class Parser extends Transform {
|
|
16
|
-
config: ParserConfiguration;
|
|
17
|
-
delimiterByte: number;
|
|
18
|
-
quoteByte: number;
|
|
19
|
-
quotequoteRegExp: RegExp;
|
|
20
|
-
escapeByte: number;
|
|
21
|
-
escapeQuoteRegExp: RegExp;
|
|
22
|
-
byteBuffer: Buffer;
|
|
23
|
-
cellBuffer: string[];
|
|
24
|
-
constructor(config?: ParserConfiguration);
|
|
25
|
-
protected writeRow(cells: string[]): void;
|
|
26
|
-
flush(callback: (error?: Error) => void, nonfinal: boolean): void;
|
|
27
|
-
_flush(callback: (error?: Error) => void): void;
|
|
28
|
-
_transform(chunk: Buffer, encoding: string, callback: (error?: Error) => void): void;
|
|
29
|
-
}
|
package/parser.js
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || function (d, b) {
|
|
3
|
-
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
|
4
|
-
function __() { this.constructor = d; }
|
|
5
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
6
|
-
};
|
|
7
|
-
var stream_1 = require('stream');
|
|
8
|
-
var common_1 = require('./common');
|
|
9
|
-
exports.defaultParserConfiguration = {
|
|
10
|
-
encoding: 'utf8',
|
|
11
|
-
missing: '',
|
|
12
|
-
newline: '\n',
|
|
13
|
-
// omit delimiter so that it gets inferred
|
|
14
|
-
quotechar: '"',
|
|
15
|
-
escape: '\\',
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
returns a single char code (a byte) denoting the inferred delimiter.
|
|
19
|
-
*/
|
|
20
|
-
function inferDelimiter(buffer) {
|
|
21
|
-
var counts = {};
|
|
22
|
-
// we look at the first newline or 256 chars, whichever is greater,
|
|
23
|
-
// but without going through the whole file
|
|
24
|
-
var upto = Math.min(256, buffer.length);
|
|
25
|
-
for (var i = 0; i < upto && buffer[i] != 10 && buffer[i] != 13; i++) {
|
|
26
|
-
var charCode = buffer[i];
|
|
27
|
-
counts[charCode] = (counts[charCode] || 0) + 1;
|
|
28
|
-
}
|
|
29
|
-
// we'll go through, prioritizing characters that aren't likely to show
|
|
30
|
-
// up unless they are a delimiter.
|
|
31
|
-
var candidates = [
|
|
32
|
-
9,
|
|
33
|
-
59,
|
|
34
|
-
44,
|
|
35
|
-
32,
|
|
36
|
-
];
|
|
37
|
-
// TODO: make this more robust (that's why I even counted them)
|
|
38
|
-
for (var candidate = void 0, j = 0; (candidate = candidates[j]); j++) {
|
|
39
|
-
if (counts[candidate] > 0) {
|
|
40
|
-
return candidate;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
exports.inferDelimiter = inferDelimiter;
|
|
45
|
-
/**
|
|
46
|
-
- `byteBuffer` is a buffer (of bytes) that have yet to be processed (and sent to output).
|
|
47
|
-
- `cellBuffer` is a list of strings that have yet to be processed (and sent to output).
|
|
48
|
-
|
|
49
|
-
*/
|
|
50
|
-
var Parser = (function (_super) {
|
|
51
|
-
__extends(Parser, _super);
|
|
52
|
-
function Parser(config) {
|
|
53
|
-
if (config === void 0) { config = {}; }
|
|
54
|
-
_super.call(this, {
|
|
55
|
-
decodeStrings: true,
|
|
56
|
-
readableObjectMode: true,
|
|
57
|
-
writableObjectMode: false,
|
|
58
|
-
});
|
|
59
|
-
this.byteBuffer = new Buffer(0);
|
|
60
|
-
this.cellBuffer = [];
|
|
61
|
-
// merge defaults
|
|
62
|
-
this.config = common_1.merge(config, exports.defaultParserConfiguration);
|
|
63
|
-
// special demarcating characters
|
|
64
|
-
// 1. delimiter
|
|
65
|
-
if (this.config.delimiter) {
|
|
66
|
-
this.delimiterByte = this.config.delimiter.charCodeAt(0);
|
|
67
|
-
}
|
|
68
|
-
// 2. quote
|
|
69
|
-
this.quoteByte = this.config.quotechar.charCodeAt(0);
|
|
70
|
-
this.quotequoteRegExp = new RegExp(this.config.quotechar + this.config.quotechar, 'g');
|
|
71
|
-
// 3. escape
|
|
72
|
-
this.escapeByte = this.config.escape.charCodeAt(0);
|
|
73
|
-
this.escapeQuoteRegExp = new RegExp('\\' + this.config.escape + this.config.quotechar, 'g');
|
|
74
|
-
}
|
|
75
|
-
Parser.prototype.writeRow = function (cells) {
|
|
76
|
-
if (!this.config.columns) {
|
|
77
|
-
// we don't emit the column names as data
|
|
78
|
-
this.config.columns = cells;
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
this.push(common_1.zip(this.config.columns, cells, this.config.missing));
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
Parser.prototype.flush = function (callback, nonfinal) {
|
|
85
|
-
var buffer = this.byteBuffer;
|
|
86
|
-
var cells = this.cellBuffer;
|
|
87
|
-
if (!this.delimiterByte) {
|
|
88
|
-
// should we wait for some minimum amount of data?
|
|
89
|
-
this.delimiterByte = inferDelimiter(buffer);
|
|
90
|
-
}
|
|
91
|
-
var start = 0;
|
|
92
|
-
var end = buffer.length;
|
|
93
|
-
var inside_quote = false;
|
|
94
|
-
// outside_quote reminds us to remove the quotes later (in pushCell)
|
|
95
|
-
var outside_quote = false;
|
|
96
|
-
for (var i = 0; i < end; i++) {
|
|
97
|
-
var eos = !nonfinal && i + 1 == end;
|
|
98
|
-
// const snippet = buffer.toString('utf8', 0, i) +
|
|
99
|
-
// '\x1b[7m' + buffer.toString('utf8', i, i + 1) + '\x1b[0m' +
|
|
100
|
-
// buffer.toString('utf8', i + 1, end);
|
|
101
|
-
// console.error(snippet.replace(/\n/g, 'N').replace(/\t/g, 'T'), inside_quote ? 'inside_quote' : '');
|
|
102
|
-
// if we are on an escape char, simply skip over it (++) and the (default)
|
|
103
|
-
if (!eos && buffer[i] == this.escapeByte) {
|
|
104
|
-
// excel is bizarre. An escape before a quotebyte doesn't count,
|
|
105
|
-
// so we only increment if the next character is not a quotebyte
|
|
106
|
-
// unless we are not inside quotes, in which case we do skip over it.
|
|
107
|
-
if (!inside_quote || buffer[i + 1] !== this.quoteByte) {
|
|
108
|
-
i++;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
else if (!eos && buffer[i] === this.quoteByte && inside_quote) {
|
|
112
|
-
// if we are inside, and on a "
|
|
113
|
-
// handle excel dialect: double quotebyte => single literal quotebyte
|
|
114
|
-
if (buffer[i + 1] === this.quoteByte) {
|
|
115
|
-
// double quotebyte
|
|
116
|
-
// we just advance over it for now, so that we can put this back on the buffer, if needed.
|
|
117
|
-
i++;
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
// lone quotebyte -> don't assume that they're always followed by a delimiter.
|
|
121
|
-
// they might be followed by a newline
|
|
122
|
-
// and we advance so that buffer[i] skips over the delimiter
|
|
123
|
-
inside_quote = false;
|
|
124
|
-
outside_quote = true;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
else if (!eos && buffer[i] === this.quoteByte && !inside_quote && i == start) {
|
|
128
|
-
// if we are not already inside, and on a "
|
|
129
|
-
inside_quote = true;
|
|
130
|
-
}
|
|
131
|
-
else if (
|
|
132
|
-
// if we are at the very end of the input and this is the final chunk (ignoring any sort of state)
|
|
133
|
-
eos ||
|
|
134
|
-
// OR, we push a new cell whenever we hit a delimiter (say, tab) and are not inside a quote
|
|
135
|
-
(!inside_quote && (buffer[i] == 13 || buffer[i] == 10 || buffer[i] == this.delimiterByte))) {
|
|
136
|
-
// this generally won't hurt, since it will only go to the end of the buffer anyway.
|
|
137
|
-
if (eos)
|
|
138
|
-
i++;
|
|
139
|
-
// add the unprocessed buffer to our cells
|
|
140
|
-
// inside_quote might be true if the file ends on a quote
|
|
141
|
-
if (inside_quote || outside_quote) {
|
|
142
|
-
var trimmed_cell = buffer.toString(this.config.encoding, start + 1, i - 1);
|
|
143
|
-
if (this.quotequoteRegExp) {
|
|
144
|
-
trimmed_cell = trimmed_cell.replace(this.quotequoteRegExp, this.config.quotechar);
|
|
145
|
-
}
|
|
146
|
-
// is this good enough?
|
|
147
|
-
cells.push(trimmed_cell);
|
|
148
|
-
outside_quote = inside_quote = false;
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
var cell = buffer.toString(this.config.encoding, start, i);
|
|
152
|
-
if (this.escapeQuoteRegExp) {
|
|
153
|
-
cell = cell.replace(this.escapeQuoteRegExp, this.config.quotechar);
|
|
154
|
-
}
|
|
155
|
-
cells.push(cell);
|
|
156
|
-
}
|
|
157
|
-
// handle \r, \r\n, or \n (but not \n\n) as one line break
|
|
158
|
-
// '\r' == 13, '\n' == 10
|
|
159
|
-
// we flush the row, also, if we are at the end and this is the final chunk
|
|
160
|
-
if (eos || (buffer[i] != this.delimiterByte)) {
|
|
161
|
-
// add these cells to the emit queue
|
|
162
|
-
this.writeRow(cells);
|
|
163
|
-
// and reset them
|
|
164
|
-
cells = [];
|
|
165
|
-
// also consume a following \n, if this was \r, and there is one.
|
|
166
|
-
if (buffer[i] == 13 && buffer[i + 1] == 10) {
|
|
167
|
-
i++;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
start = i + 1;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// save whatever we have yet to process
|
|
174
|
-
this.byteBuffer = buffer.slice(start, end);
|
|
175
|
-
this.cellBuffer = cells;
|
|
176
|
-
// if there was a trailing newline, this._buffer.length = 0
|
|
177
|
-
callback();
|
|
178
|
-
};
|
|
179
|
-
Parser.prototype._flush = function (callback) {
|
|
180
|
-
return this.flush(callback, false);
|
|
181
|
-
};
|
|
182
|
-
Parser.prototype._transform = function (chunk, encoding, callback) {
|
|
183
|
-
// we'll assume that we always get chunks with the same encoding.
|
|
184
|
-
if (!this.config.encoding && encoding != 'buffer') {
|
|
185
|
-
this.config.encoding = encoding;
|
|
186
|
-
}
|
|
187
|
-
// collect unused buffer and new chunk into a single buffer
|
|
188
|
-
this.byteBuffer = this.byteBuffer.length ? Buffer.concat([this.byteBuffer, chunk]) : chunk;
|
|
189
|
-
// do all the processing
|
|
190
|
-
this.flush(callback, true);
|
|
191
|
-
};
|
|
192
|
-
return Parser;
|
|
193
|
-
}(stream_1.Transform));
|
|
194
|
-
exports.Parser = Parser;
|
package/stringifier.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Transform } from 'stream';
|
|
2
|
-
import { Configuration } from './common';
|
|
3
|
-
export interface StringifierConfiguration extends Configuration {
|
|
4
|
-
peek?: number;
|
|
5
|
-
}
|
|
6
|
-
export declare const defaultStringifierConfiguration: {
|
|
7
|
-
encoding: string;
|
|
8
|
-
missing: string;
|
|
9
|
-
newline: string;
|
|
10
|
-
delimiter: string;
|
|
11
|
-
quotechar: string;
|
|
12
|
-
escape: string;
|
|
13
|
-
peek: number;
|
|
14
|
-
};
|
|
15
|
-
export declare function inferColumns(rows: string[][]): string[];
|
|
16
|
-
/** Stringifier class
|
|
17
|
-
new Stringifier();
|
|
18
|
-
- `peek` is an integer (or undefined / null) describing how many rows we
|
|
19
|
-
should look at before inferring headers and flushing.
|
|
20
|
-
- `columns` is an array of strings once the headers have been inferred
|
|
21
|
-
- `encoding` is the encoding that the stream's read function will use.
|
|
22
|
-
- `missing` is the value we write for 'time' when we have
|
|
23
|
-
`columns = ['index', 'time']` and `write({index: 90})` is called
|
|
24
|
-
|
|
25
|
-
- `delimiter` is the field separator (defaults to a comma)
|
|
26
|
-
- `quotechar` is the character used to quote fields if they contain the
|
|
27
|
-
`delimiter` character (defaults to a double-quote)
|
|
28
|
-
|
|
29
|
-
- `_buffer` is an array of arrays or objects that need to be written
|
|
30
|
-
*/
|
|
31
|
-
export declare class Stringifier extends Transform {
|
|
32
|
-
/** should this even be 1? (ignored if opts.columns) */
|
|
33
|
-
config: StringifierConfiguration;
|
|
34
|
-
protected quotecharRegExp: RegExp;
|
|
35
|
-
protected rowBuffer: string[][];
|
|
36
|
-
constructor(config?: StringifierConfiguration);
|
|
37
|
-
protected writeObject(object: any): void;
|
|
38
|
-
protected writeObjects(objects: any[]): void;
|
|
39
|
-
flush(callback: (error?: Error) => void, nonfinal: boolean): void;
|
|
40
|
-
_flush(callback: (error?: Error) => void): void;
|
|
41
|
-
_transform(chunk: any, encoding: string, callback: (error?: Error) => void): void;
|
|
42
|
-
}
|
package/stringifier.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || function (d, b) {
|
|
3
|
-
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
|
4
|
-
function __() { this.constructor = d; }
|
|
5
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
6
|
-
};
|
|
7
|
-
var stream_1 = require('stream');
|
|
8
|
-
var common_1 = require('./common');
|
|
9
|
-
exports.defaultStringifierConfiguration = {
|
|
10
|
-
encoding: 'utf8',
|
|
11
|
-
missing: '',
|
|
12
|
-
newline: '\n',
|
|
13
|
-
delimiter: ',',
|
|
14
|
-
quotechar: '"',
|
|
15
|
-
escape: '\\',
|
|
16
|
-
peek: 1,
|
|
17
|
-
};
|
|
18
|
-
function inferColumns(rows) {
|
|
19
|
-
var columns = [];
|
|
20
|
-
var seen = {};
|
|
21
|
-
rows.forEach(function (row) {
|
|
22
|
-
// each object might be a string, array, or object, but only objects matter here.
|
|
23
|
-
if (typeof (row) !== 'string' && !Array.isArray(row)) {
|
|
24
|
-
Object.keys(row).forEach(function (key) {
|
|
25
|
-
// if (row.hasOwnProperty(key)) {
|
|
26
|
-
// maybe should also check that row[key] != null
|
|
27
|
-
if (!(key in seen)) {
|
|
28
|
-
columns.push(key);
|
|
29
|
-
seen[key] = 1;
|
|
30
|
-
}
|
|
31
|
-
// }
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
return columns;
|
|
36
|
-
}
|
|
37
|
-
exports.inferColumns = inferColumns;
|
|
38
|
-
/** Stringifier class
|
|
39
|
-
new Stringifier();
|
|
40
|
-
- `peek` is an integer (or undefined / null) describing how many rows we
|
|
41
|
-
should look at before inferring headers and flushing.
|
|
42
|
-
- `columns` is an array of strings once the headers have been inferred
|
|
43
|
-
- `encoding` is the encoding that the stream's read function will use.
|
|
44
|
-
- `missing` is the value we write for 'time' when we have
|
|
45
|
-
`columns = ['index', 'time']` and `write({index: 90})` is called
|
|
46
|
-
|
|
47
|
-
- `delimiter` is the field separator (defaults to a comma)
|
|
48
|
-
- `quotechar` is the character used to quote fields if they contain the
|
|
49
|
-
`delimiter` character (defaults to a double-quote)
|
|
50
|
-
|
|
51
|
-
- `_buffer` is an array of arrays or objects that need to be written
|
|
52
|
-
*/
|
|
53
|
-
var Stringifier = (function (_super) {
|
|
54
|
-
__extends(Stringifier, _super);
|
|
55
|
-
function Stringifier(config) {
|
|
56
|
-
if (config === void 0) { config = {}; }
|
|
57
|
-
_super.call(this, { readableObjectMode: false, writableObjectMode: true });
|
|
58
|
-
this.rowBuffer = [];
|
|
59
|
-
this.config = common_1.merge(config, exports.defaultStringifierConfiguration);
|
|
60
|
-
this.quotecharRegExp = new RegExp(this.config.quotechar, 'ig');
|
|
61
|
-
if (this.config.columns) {
|
|
62
|
-
// maybe we should write the columns even if we don't get any data?
|
|
63
|
-
this.rowBuffer = [this.config.columns];
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
this.rowBuffer = [];
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
Stringifier.prototype.writeObject = function (object) {
|
|
70
|
-
// _write is already a thing, so don't use it.
|
|
71
|
-
// this.columns must be set!
|
|
72
|
-
if (typeof (object) === 'string') {
|
|
73
|
-
// raw string
|
|
74
|
-
this.push(object + this.config.newline, this.config.encoding);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
// if object is an array, we ignore this.columns
|
|
78
|
-
var length_1 = object.length;
|
|
79
|
-
if (!Array.isArray(object)) {
|
|
80
|
-
// object
|
|
81
|
-
length_1 = this.config.columns.length;
|
|
82
|
-
// pull properties off the given object in proper column order
|
|
83
|
-
var list = new Array(length_1);
|
|
84
|
-
for (var i = 0; i < length_1; i++) {
|
|
85
|
-
var column_value = object[this.config.columns[i]];
|
|
86
|
-
list[i] = (column_value === undefined) ? this.config.missing : column_value;
|
|
87
|
-
}
|
|
88
|
-
object = list;
|
|
89
|
-
}
|
|
90
|
-
// obj is definitely an array now, but the fields aren't quoted.
|
|
91
|
-
for (var j = 0; j < length_1; j++) {
|
|
92
|
-
// assume minimal quoting (don't quote unless the cell contains the delimiter)
|
|
93
|
-
var value = String(object[j]);
|
|
94
|
-
var contains_newline = value.indexOf('\n') > -1 || value.indexOf('\r') > -1;
|
|
95
|
-
var contains_quotechar = value.indexOf(this.config.quotechar) > -1;
|
|
96
|
-
if (value.indexOf(this.config.delimiter) > -1 || contains_newline || contains_quotechar) {
|
|
97
|
-
if (contains_quotechar) {
|
|
98
|
-
// serialize into the excel dialect, currently
|
|
99
|
-
value = value.replace(this.quotecharRegExp, this.config.quotechar + this.config.quotechar);
|
|
100
|
-
}
|
|
101
|
-
value = this.config.quotechar + value + this.config.quotechar;
|
|
102
|
-
}
|
|
103
|
-
object[j] = value;
|
|
104
|
-
}
|
|
105
|
-
this.push(object.join(this.config.delimiter) + this.config.newline, this.config.encoding);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
Stringifier.prototype.writeObjects = function (objects) {
|
|
109
|
-
for (var i = 0, l = objects.length; i < l; i++) {
|
|
110
|
-
this.writeObject(objects[i]);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
Stringifier.prototype.flush = function (callback, nonfinal) {
|
|
114
|
-
// called when we're done peeking (nonfinal = true) or when end() is
|
|
115
|
-
// called (nonfinal = false), in which case we are done peeking, but for a
|
|
116
|
-
// different reason. In either case, we need to flush the peeked columns.
|
|
117
|
-
if (!this.config.columns) {
|
|
118
|
-
// infer columns
|
|
119
|
-
this.config.columns = inferColumns(this.rowBuffer);
|
|
120
|
-
this.writeObject(this.config.columns);
|
|
121
|
-
}
|
|
122
|
-
if (this.rowBuffer) {
|
|
123
|
-
// flush the _buffer
|
|
124
|
-
this.writeObjects(this.rowBuffer);
|
|
125
|
-
// a null _buffer means we're done peeking and won't be buffering any more rows
|
|
126
|
-
this.rowBuffer = null;
|
|
127
|
-
}
|
|
128
|
-
// this.push(null); // inferred
|
|
129
|
-
callback();
|
|
130
|
-
};
|
|
131
|
-
// the docs decree that we shouldn't call _flush directly
|
|
132
|
-
Stringifier.prototype._flush = function (callback) {
|
|
133
|
-
return this.flush(callback, false);
|
|
134
|
-
};
|
|
135
|
-
Stringifier.prototype._transform = function (chunk, encoding, callback) {
|
|
136
|
-
// objectMode: true, so chunk is an object (and encoding is always 'utf8'?)
|
|
137
|
-
if (this.config.columns) {
|
|
138
|
-
// flush the _buffer, if needed
|
|
139
|
-
if (this.rowBuffer) {
|
|
140
|
-
this.writeObjects(this.rowBuffer);
|
|
141
|
-
this.rowBuffer = null;
|
|
142
|
-
}
|
|
143
|
-
this.writeObject(chunk);
|
|
144
|
-
callback();
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
// if set {peek: 10}, column inference will be called when write(obj) is called the 10th time
|
|
148
|
-
this.rowBuffer.push(chunk);
|
|
149
|
-
if (this.rowBuffer.length >= this.config.peek) {
|
|
150
|
-
this.flush(callback, true);
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
callback();
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
return Stringifier;
|
|
158
|
-
}(stream_1.Transform));
|
|
159
|
-
exports.Stringifier = Stringifier;
|