mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
parent
506439afd6
commit
cc6e465333
@ -79,7 +79,8 @@ export async function parseRecord(
|
||||
const separatorLen = opt.separator.length;
|
||||
let recordBuffer = "";
|
||||
const fieldIndexes = [] as number[];
|
||||
parseField: while (true) {
|
||||
parseField:
|
||||
for (;;) {
|
||||
if (opt.trimLeadingSpace) {
|
||||
line = line.trimStart();
|
||||
}
|
||||
@ -117,7 +118,7 @@ export async function parseRecord(
|
||||
} else {
|
||||
// Quoted string field
|
||||
line = line.substring(quoteLen);
|
||||
while (true) {
|
||||
for (;;) {
|
||||
const i = line.indexOf(quote);
|
||||
if (i >= 0) {
|
||||
// Hit next quote.
|
||||
|
@ -74,21 +74,32 @@ 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) {
|
||||
controller.enqueue(
|
||||
stringify([columns], { separator, headers: false }),
|
||||
);
|
||||
try {
|
||||
controller.enqueue(
|
||||
stringify([columns], { separator, headers: false }),
|
||||
);
|
||||
} catch (error) {
|
||||
controller.error(error);
|
||||
}
|
||||
}
|
||||
},
|
||||
transform(chunk, controller) {
|
||||
controller.enqueue(
|
||||
stringify([chunk], { separator, headers: false, columns }),
|
||||
);
|
||||
try {
|
||||
controller.enqueue(
|
||||
stringify([chunk], { separator, headers: false, columns }),
|
||||
);
|
||||
} catch (error) {
|
||||
controller.error(error);
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
|
29
csv/parse.ts
29
csv/parse.ts
@ -103,7 +103,8 @@ class Parser {
|
||||
const separatorLen = this.#options.separator.length;
|
||||
let recordBuffer = "";
|
||||
const fieldIndexes = [] as number[];
|
||||
parseField: while (true) {
|
||||
parseField:
|
||||
for (;;) {
|
||||
if (this.#options.trimLeadingSpace) {
|
||||
line = line.trimStart();
|
||||
}
|
||||
@ -141,7 +142,7 @@ class Parser {
|
||||
} else {
|
||||
// Quoted string field
|
||||
line = line.substring(quoteLen);
|
||||
while (true) {
|
||||
for (;;) {
|
||||
const i = line.indexOf(quote);
|
||||
if (i >= 0) {
|
||||
// Hit next quote.
|
||||
@ -249,7 +250,7 @@ class Parser {
|
||||
throw new Error(ERR_INVALID_DELIM);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
for (;;) {
|
||||
const r = this.#parseRecord(lineIndex);
|
||||
if (r === null) break;
|
||||
lineResult = r;
|
||||
@ -328,35 +329,35 @@ export function parse(input: string): string[][];
|
||||
*
|
||||
* @typeParam T The options' type for parsing.
|
||||
* @param input The input to parse.
|
||||
* @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>[]`.
|
||||
* @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>[]`.
|
||||
*/
|
||||
export function parse<const T extends ParseOptions>(
|
||||
input: string,
|
||||
options: T,
|
||||
opt: T,
|
||||
): ParseResult<ParseOptions, T>;
|
||||
export function parse<const T extends ParseOptions>(
|
||||
input: string,
|
||||
options: T = { skipFirstRow: false } as T,
|
||||
opt: T = { skipFirstRow: false } as T,
|
||||
): ParseResult<ParseOptions, T> {
|
||||
const parser = new Parser(options);
|
||||
const parser = new Parser(opt);
|
||||
const r = parser.parse(input);
|
||||
|
||||
if (options.skipFirstRow || options.columns) {
|
||||
if (opt.skipFirstRow || opt.columns) {
|
||||
let headers: readonly string[] = [];
|
||||
|
||||
if (options.skipFirstRow) {
|
||||
if (opt.skipFirstRow) {
|
||||
const head = r.shift();
|
||||
if (head === undefined) throw new TypeError("Headers must be defined");
|
||||
headers = head;
|
||||
}
|
||||
|
||||
if (options.columns) {
|
||||
headers = options.columns;
|
||||
if (opt.columns) {
|
||||
headers = opt.columns;
|
||||
}
|
||||
|
||||
const firstLineIndex = options.skipFirstRow ? 1 : 0;
|
||||
const firstLineIndex = opt.skipFirstRow ? 1 : 0;
|
||||
return r.map((row, i) => {
|
||||
return convertRowToObject(row, headers, firstLineIndex + i);
|
||||
}) as ParseResult<ParseOptions, T>;
|
||||
|
@ -104,11 +104,9 @@ 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[];
|
||||
/**
|
||||
@ -297,16 +295,13 @@ 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[],
|
||||
options?: StringifyOptions,
|
||||
{ headers = true, separator: sep = ",", columns = [], bom = false }:
|
||||
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:",
|
||||
|
Loading…
Reference in New Issue
Block a user