diff --git a/packages/csv-parse/lib/index.d.ts b/packages/csv-parse/lib/index.d.ts index 7119d61e..c6fa01d9 100644 --- a/packages/csv-parse/lib/index.d.ts +++ b/packages/csv-parse/lib/index.d.ts @@ -93,9 +93,37 @@ export type ColumnOption = | false | { name: K }; +export interface InfoDelimiterAuto { + /** + * The character code of the delimiter candidate being scored. + */ + readonly char_code: number; + /** + * The number of occurrences of the candidate in each line. + */ + readonly lines: number[]; + /** + * Whether the candidate is listed in the `preferred` option. + */ + readonly preferred: boolean; + /** + * The standard deviation of the occurrences across the lines. + */ + readonly std: number; + /** + * The total number of occurrences of the candidate. + */ + readonly total: number; +} + +export type ScoringFunction = ( + info: InfoDelimiterAuto, + options: OptionDelimiterAuto, +) => number; + export interface OptionDelimiterAuto { preferred: Record; - score: () => number; + score: ScoringFunction; size: number; } diff --git a/packages/csv-parse/test/option.delimiter_auto.ts b/packages/csv-parse/test/option.delimiter_auto.ts index 4bd7e1f8..b03f166e 100644 --- a/packages/csv-parse/test/option.delimiter_auto.ts +++ b/packages/csv-parse/test/option.delimiter_auto.ts @@ -38,6 +38,33 @@ describe("Option `delimiter_auto`", function () { ]); }); + it("sync custom score", function () { + // The default score elects `;` because it is more preferred than `:` + parse_sync("a:b;c\nd:e;f", { + delimiter_auto: true, + }).should.eql([ + ["a:b", "c"], + ["d:e", "f"], + ]); + // A custom score receives the candidate info and the normalized options + const char_codes: number[] = []; + parse_sync("a:b;c\nd:e;f", { + delimiter_auto: { + score: (info, options) => { + char_codes.push(info.char_code); + return info.char_code === ":".charCodeAt(0) + ? 100 + : (info.total - info.std) * + (options.preferred[info.char_code] || 1); + }, + }, + }).should.eql([ + ["a", "b;c"], + ["d", "e;f"], + ]); + char_codes.length.should.eql(127); + }); + it("stream smaller than size", function (next) { let content = ""; for (let i = 0; i < 10; i++) {