DEV Community

Zengkkj
Zengkkj

Posted on

Crow Docs v22: Fixing 12 bugs across an offline-first PDF toolkit

What is Crow Docs?

Crow Docs is a free, open-source, browser-based document toolkit. Merge, split, compress, sign, translate, OCR, compare, booklet, metadata editing, Markdown-to-slides, image-to-PDF, PDF-to-audio, PDF-to-PPTX — it does a lot.

The key detail: everything runs 100% client-side. No file uploads. No server processing. Your documents never leave your device. It's a PWA, so it works offline too.

The email that started everything
A user wrote in with two issues: "the PPTX export doesn't open in PowerPoint" and "GIFs in my PDF don't animate."

Fair feedback. But instead of patching just those two things, I decided to audit every tool in the app. What I found was humbling — 12 bugs across the entire toolkit, some hiding in plain sight for months.

The 12 bugs (and why they existed)

  1. PDF to PPTX wouldn't open in PowerPoint — Google Slides is forgiving about missing OOXML structure. PowerPoint is not. Added proper theme, clrMap, txStyles, grpSpPr transforms, and docProps.

  2. QR codes wouldn't scan — Custom inline QR encoder had subtle bugs. Replaced with the battle-tested qrcode-generator library.

  3. Compare PDFs showed NaN — ImageData dimensions mismatch when PDFs had different page sizes. Fixed by normalizing to same-size canvas.

  4. Booklet page ordering was wrong — Saddle-stitch imposition algorithm had incorrect formula for inner sheets. Corrected: outerLeft = total-1-s*2, outerRight = s*2, innerLeft = s*2+1, innerRight = total-2-s*2.

  5. Markdown to Slides splitting failed — Regex didn't handle whitespace around --- or Windows \r\n line endings.

  6. Translate PDF lost paragraphs — join(' ') instead of join('\n'). One character, all paragraphs gone.

  7. PDF metadata keywords stored incorrectly — Saved as single-element array instead of splitting by comma.

  8. Sign PDF crash — No null check on canvas element before drawing.

  9. Organize PDF used generic filename — Now preserves the original filename.

  10. GIF in PDF — no warning — PDFs don't support animation. Added toast notification explaining the limitation.

  11. OCR errors showed "undefined" — Six catch blocks used e.message without fallback. Fixed with e?.message || String(e).

  12. Header/footer regex typo — /^Página?/ matched "Págin" instead of "Página". Fixed to /^P[aá]gina/i.

Lessons learned
PowerPoint doesn't forgive. Google Slides will render a half-valid PPTX. PowerPoint will reject it. Test against the strictest consumer.

Users find what tests don't. A real person trying to open your file in their specific environment — that's where edge cases live.

Self-hosting dependencies pays off. Every library lives in /libs/. No CDN calls. The offline story is bulletproof because there are zero external runtime requests.

Tech stack
Vanilla JS. No frameworks, no build step. The heavy lifting comes from: pdf-lib, jsPDF, PDF.js, Tesseract.js, JSZip, mammoth, docx, and qrcode-generator.

Try it, break it, tell me

Top comments (0)