Compare commits

...

3 Commits

Author SHA1 Message Date
0xtoshii 48789a96d4 changeset: 2025-05-29 16:38:11 -07:00
0xtoshii aa803d99d8 parsing 2025-05-29 16:36:46 -07:00
0xtoshii f5add5ee43 package 2025-05-29 12:03:04 -07:00
5 changed files with 1170 additions and 9 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"claude-dev": minor
---
add suppport for parsing csv and xlsx
+1065 -8
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -373,6 +373,7 @@
"clone-deep": "^4.0.1",
"default-shell": "^2.2.0",
"diff": "^5.2.0",
"exceljs": "^4.4.0",
"execa": "^9.5.2",
"fast-deep-equal": "^3.1.3",
"firebase": "^11.2.0",
+98
View File
@@ -6,6 +6,7 @@ import fs from "fs/promises"
import { isBinaryFile } from "isbinaryfile"
import * as chardet from "jschardet"
import * as iconv from "iconv-lite"
import ExcelJS from "exceljs"
export async function detectEncoding(fileBuffer: Buffer, fileExtension?: string): Promise<string> {
const detected = chardet.detect(fileBuffer)
@@ -38,6 +39,8 @@ export async function extractTextFromFile(filePath: string): Promise<string> {
return extractTextFromDOCX(filePath)
case ".ipynb":
return extractTextFromIPYNB(filePath)
case ".xlsx":
return extractTextFromExcel(filePath)
default:
const fileBuffer = await fs.readFile(filePath)
if (fileBuffer.byteLength > 20 * 1000 * 1024) {
@@ -76,6 +79,101 @@ async function extractTextFromIPYNB(filePath: string): Promise<string> {
return extractedText
}
/**
* Format the data inside Excel cells
*/
function formatCellValue(cell: ExcelJS.Cell): string {
const value = cell.value
if (value === null || value === undefined) {
return ""
}
// Handle error values (#DIV/0!, #N/A, etc.)
if (typeof value === "object" && "error" in value) {
return `[Error: ${value.error}]`
}
// Handle dates - ExcelJS can parse them as Date objects
if (value instanceof Date) {
return value.toISOString().split("T")[0] // Just the date part
}
// Handle rich text
if (typeof value === "object" && "richText" in value) {
return value.richText.map((rt) => rt.text).join("")
}
// Handle hyperlinks
if (typeof value === "object" && "text" in value && "hyperlink" in value) {
return `${value.text} (${value.hyperlink})`
}
// Handle formulas - get the calculated result
if (typeof value === "object" && "formula" in value) {
if ("result" in value && value.result !== undefined && value.result !== null) {
return value.result.toString()
} else {
return `[Formula: ${value.formula}]`
}
}
return value.toString()
}
/**
* Extract and format text from xlsx files
*/
async function extractTextFromExcel(filePath: string): Promise<string> {
const workbook = new ExcelJS.Workbook()
let excelText = ""
try {
await workbook.xlsx.readFile(filePath)
workbook.eachSheet((worksheet, sheetId) => {
// Skip hidden sheets
if (worksheet.state === "hidden" || worksheet.state === "veryHidden") {
return
}
excelText += `--- Sheet: ${worksheet.name} ---\n`
worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
// Optional: limit processing for very large sheets
if (rowNumber > 50000) {
excelText += `[... truncated at row ${rowNumber} ...]\n`
return false
}
const rowTexts: string[] = []
let hasContent = false
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
const cellText = formatCellValue(cell)
if (cellText.trim()) {
hasContent = true
}
rowTexts.push(cellText)
})
// Only add rows with actual content
if (hasContent) {
excelText += rowTexts.join("\t") + "\n"
}
return true
})
excelText += "\n" // Blank line between sheets
})
return excelText.trim()
} catch (error: any) {
console.error(`Error extracting text from Excel ${filePath}:`, error)
throw new Error(`Failed to extract text from Excel: ${error.message}`)
}
}
/**
* Helper function used to load file(s) and format them into a string
*/
+1 -1
View File
@@ -9,7 +9,7 @@ import sizeOf from "image-size"
*/
export async function selectFiles(imagesAllowed: boolean): Promise<{ images: string[]; files: string[] }> {
const IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "webp"] // supported by anthropic and openrouter
const OTHER_FILE_EXTENSIONS = ["xml", "json", "txt", "log", "md", "docx", "ipynb", "pdf"]
const OTHER_FILE_EXTENSIONS = ["xml", "json", "txt", "log", "md", "docx", "ipynb", "pdf", "xlsx", "csv"]
const options: vscode.OpenDialogOptions = {
canSelectMany: true,