Spaces:
Sleeping
Sleeping
File size: 2,403 Bytes
05c5ed5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | import { Buffer } from "node:buffer";
export type CsvPreview = {
header: string[];
rows: string[][]; // limited by maxRows/maxCols
columns: number;
totalRows: number;
markdownTable: string; // simple markdown table for the chat
};
export function parseCsvPreview(
content: Buffer,
opts: { maxRows?: number; maxCols?: number } = {},
): CsvPreview {
const maxRows = Math.max(1, opts.maxRows ?? 50);
const maxCols = Math.max(1, opts.maxCols ?? 12);
const text = content.toString("utf8");
const rows: string[][] = [];
let i = 0;
let field = "";
let inQuotes = false;
let row: string[] = [];
const pushField = () => {
row.push(field);
field = "";
};
const pushRow = () => {
rows.push(row);
row = [];
};
while (i < text.length) {
const ch = text[i++];
if (inQuotes) {
if (ch === '"') {
if (text[i] === '"') {
field += '"';
i++;
} else {
inQuotes = false;
}
} else {
field += ch;
}
} else {
if (ch === '"') {
inQuotes = true;
} else if (ch === ",") {
pushField();
} else if (ch === "\n") {
pushField();
pushRow();
} else if (ch === "\r") {
// ignore CR (handle CRLF)
} else {
field += ch;
}
}
}
// flush last field/row
pushField();
if (row.some(field => field !== "")) pushRow();
const totalRows = rows.length;
const header = rows[0] ?? [];
const limitedHeader = header.slice(0, maxCols);
const dataRows = rows.slice(1);
const limitedRows = dataRows
.slice(0, maxRows)
.map((r) => r.slice(0, maxCols));
const columns = limitedHeader.length;
const mdHeader = `| ${limitedHeader.join(" | ")} |`;
const mdSep = `| ${limitedHeader.map(() => "---").join(" | ")} |`;
const mdBody = limitedRows
.map(
(r) => `| ${r.map((c) => (c ?? "").replace(/\|/g, "\\|")).join(" | ")} |`,
)
.join("\n");
const markdownTable = [mdHeader, mdSep, mdBody].join("\n");
return {
header: limitedHeader,
rows: limitedRows,
columns,
totalRows,
markdownTable,
};
}
export const formatCsvPreviewText = (
name: string,
preview: CsvPreview,
): string => {
return `Here is a preview of ${name} (rows: ${preview.totalRows}, cols: ${preview.columns}). Summarize or analyze as needed.\n\n${preview.markdownTable}`;
};
|