feat: add CSV to PDF operation - #179
slegarraga wants to merge 2 commits into
Conversation
New src/operations/excel-to-pdf/ plugin: parses .xlsx/.csv fully client-side with SheetJS and lays each sheet out as a paginated landscape table via jsPDF. - Multi-sheet workbooks: one titled section per sheet, empty sheets skipped - Column widths derived from content, long cells truncated with ellipsis - Header row bold with rule, repeated after page breaks - Values only: formatting, merged cells and styles don't carry over (stated in the tool's result note per the issue's honesty requirement) - Empty workbook or all-empty sheets fail with a clear error Verified: real .xlsx (2 sheets) and .csv fixtures converted through the actual helper code to valid %PDF-1.3 output; eslint clean; vite build green with the operation embedded in the bundle.
|
@slegarraga is attempting to deploy a commit to the Mithun Srinivas' projects Team on Vercel. A member of the Team first needs to authorize it. |
The CI run for mithun-srinivas#179 failed with 'Timed out waiting 15000ms from config.webServer': the build step inside the webServer command can exceed 15s on cold caches (our PR adds the xlsx dependency, growing the bundle). 60s gives headroom; local runs are unaffected because reuseExistingServer skips this path outside CI. Verified locally: npx playwright test → 5 passed (33.2s) with the new timeout in place.
|
Thanks for this @slegarraga, the layout code is genuinely nice: the paginated table, the repeated header row on page breaks, the ellipsis truncation, and the honest "values only" note are all exactly right. The one thing I want to change before merging is the dependency. Pulling in So let's rescope this to CSV only and drop SheetJS entirely. CSV covers the common case, needs no dependency, and keeps the whole thing tiny. The jsPDF table layout you already wrote can stay exactly as is; only the parsing step changes. A small inline CSV parser (handles quoted fields and escaped quotes) is all you need in place of function parseCsv(text) {
const rows = []
let row = [], field = '', inQuotes = false
for (let i = 0; i < text.length; i++) {
const c = text[i]
if (inQuotes) {
if (c === '"' && text[i + 1] === '"') { field += '"'; i++ }
else if (c === '"') inQuotes = false
else field += c
} else if (c === '"') inQuotes = true
else if (c === ',') { row.push(field); field = '' }
else if (c === '\n') { row.push(field); rows.push(row); row = []; field = '' }
else if (c !== '\r') field += c
}
if (field.length || row.length) { row.push(field); rows.push(row) }
return rows.filter(r => r.some(cell => cell.trim() !== ''))
}Then the helper becomes roughly:
Everything else you did carries straight over. Thanks again, this is close! |
|
Thank you for such a thoughtful review! I rescoped this to CSV-only and removed SheetJS entirely. The parser now handles quoted fields, escaped quotes, CRLF, embedded delimiters/newlines, and blank-row filtering; column widths use reduce loops instead of spread aggregation. I added focused Vitest coverage, verified lint/format/build, converted a real fixture through the helper, and confirmed |
|
Closing this one as superseded. We decided to take #172 in a CSV-only direction to avoid the SheetJS dependency and its unpatched advisories, and there's now a CSV-only implementation in #188 that takes that approach. Rather than have two PRs on the same issue, I'm closing this in favor of that one. Thanks a lot for the original work here @slegarraga, the jsPDF table layout you wrote was solid and it's what pointed the way. You've got other PRs of yours still in flight (#177, #181), so nothing lost. Appreciate it! |
Closes #172
Rescoped from Excel/CSV to CSV only after review, removing the vulnerable
xlsxdependency while keeping the existing paginated table layout.What
src/operations/csv-to-pdf/as a self-contained client-side operation.Verification
npm cinpm run lintnpm test— includes parser coverage for quoted fields/escaped quotes, CRLF, embedded delimiters/newlines, blank-row filtering, and empty-input rejection.npm run buildnpm run format:check%PDF-1.7blob with the expected row count.xlsxand SheetJS are absent frompackage.json,package-lock.json, source, and build output.