refactor(csv): minor cleanups (#5158)

* refactor(csv): minor cleanups

* fix
This commit is contained in:
Asher Gomez 2024-06-27 14:27:13 +10:00 committed by GitHub
parent c8a88593a2
commit 506439afd6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 31 additions and 39 deletions

View File

@ -79,8 +79,7 @@ export async function parseRecord(
const separatorLen = opt.separator.length;
let recordBuffer = "";
const fieldIndexes = [] as number[];
parseField:
for (;;) {
parseField: while (true) {
if (opt.trimLeadingSpace) {
line = line.trimStart();
}
@ -118,7 +117,7 @@ export async function parseRecord(
} else {
// Quoted string field
line = line.substring(quoteLen);
for (;;) {
while (true) {
const i = line.indexOf(quote);
if (i >= 0) {
// Hit next quote.

View File

@ -74,32 +74,21 @@ export class CsvStringifyStream<TOptions extends CsvStringifyStreamOptions>
* @param options Options for the stream.
*/
constructor(options?: TOptions) {
const {
separator,
columns = [],
} = options ?? {};
const { separator, columns = [] } = options ?? {};
super(
{
start(controller) {
if (columns && columns.length > 0) {
try {
controller.enqueue(
stringify([columns], { separator, headers: false }),
);
} catch (error) {
controller.error(error);
}
controller.enqueue(
stringify([columns], { separator, headers: false }),
);
}
},
transform(chunk, controller) {
try {
controller.enqueue(
stringify([chunk], { separator, headers: false, columns }),
);
} catch (error) {
controller.error(error);
}
controller.enqueue(
stringify([chunk], { separator, headers: false, columns }),
);
},
},
);

View File

@ -103,8 +103,7 @@ class Parser {
const separatorLen = this.#options.separator.length;
let recordBuffer = "";
const fieldIndexes = [] as number[];
parseField:
for (;;) {
parseField: while (true) {
if (this.#options.trimLeadingSpace) {
line = line.trimStart();
}
@ -142,7 +141,7 @@ class Parser {
} else {
// Quoted string field
line = line.substring(quoteLen);
for (;;) {
while (true) {
const i = line.indexOf(quote);
if (i >= 0) {
// Hit next quote.
@ -250,7 +249,7 @@ class Parser {
throw new Error(ERR_INVALID_DELIM);
}
for (;;) {
while (true) {
const r = this.#parseRecord(lineIndex);
if (r === null) break;
lineResult = r;
@ -329,35 +328,35 @@ export function parse(input: string): string[][];
*
* @typeParam T The options' type for parsing.
* @param input The input to parse.
* @param opt The options for parsing.
* @returns If you don't provide `opt.skipFirstRow` and `opt.columns`, it returns `string[][]`.
* If you provide `opt.skipFirstRow` or `opt.columns`, it returns `Record<string, unknown>[]`.
* @param options The options for parsing.
* @returns If you don't provide `options.skipFirstRow` and `options.columns`, it returns `string[][]`.
* If you provide `options.skipFirstRow` or `options.columns`, it returns `Record<string, unknown>[]`.
*/
export function parse<const T extends ParseOptions>(
input: string,
opt: T,
options: T,
): ParseResult<ParseOptions, T>;
export function parse<const T extends ParseOptions>(
input: string,
opt: T = { skipFirstRow: false } as T,
options: T = { skipFirstRow: false } as T,
): ParseResult<ParseOptions, T> {
const parser = new Parser(opt);
const parser = new Parser(options);
const r = parser.parse(input);
if (opt.skipFirstRow || opt.columns) {
if (options.skipFirstRow || options.columns) {
let headers: readonly string[] = [];
if (opt.skipFirstRow) {
if (options.skipFirstRow) {
const head = r.shift();
if (head === undefined) throw new TypeError("Headers must be defined");
headers = head;
}
if (opt.columns) {
headers = opt.columns;
if (options.columns) {
headers = options.columns;
}
const firstLineIndex = opt.skipFirstRow ? 1 : 0;
const firstLineIndex = options.skipFirstRow ? 1 : 0;
return r.map((row, i) => {
return convertRowToObject(row, headers, firstLineIndex + i);
}) as ParseResult<ParseOptions, T>;

View File

@ -104,9 +104,11 @@ export type StringifyOptions = {
*/
separator?: string;
/**
* a list of instructions for how to target and transform the data for each
* A list of instructions for how to target and transform the data for each
* column of output. This is also where you can provide an explicit header
* name for the column.
*
* @default {[]}
*/
columns?: Column[];
/**
@ -295,13 +297,16 @@ function getValuesFromItem(
*
* @param data The source data to stringify. It's an array of items which are
* plain objects or arrays.
* @param options Options for the stringification.
* @returns A CSV string.
*/
export function stringify(
data: DataItem[],
{ headers = true, separator: sep = ",", columns = [], bom = false }:
StringifyOptions = {},
options?: StringifyOptions,
): string {
const { headers = true, separator: sep = ",", columns = [], bom = false } =
options ?? {};
if (sep.includes(QUOTE) || sep.includes(CRLF)) {
const message = [
"Separator cannot include the following strings:",