Skip to content

feat(pdf): File Convert category + PDF → image tool#100

Merged
lyfuci merged 1 commit into
mainfrom
feat/pdf-to-image
Jul 9, 2026
Merged

feat(pdf): File Convert category + PDF → image tool#100
lyfuci merged 1 commit into
mainfrom
feat/pdf-to-image

Conversation

@lyfuci

@lyfuci lyfuci commented Jul 9, 2026

Copy link
Copy Markdown
Owner

What

Adds a new top-level File Convert category (first-level menu) and its
first tool, PDF Convert (second-level), starting with PDF → image.
All rendering is client-side — nothing is uploaded and no external calls are
made.

How it works

  • pdf.js (pdfjs-dist) renders each page to a canvas. The worker is
    bundled same-origin via ?url (version-matched, COEP-safe).
  • Runtime assets — cmaps/, standard_fonts/, wasm/ — are copied into
    public/pdfjs/ and served from our own origin, not a CDN. That's
    required twice over: the site is COOP/COEP cross-origin-isolated (CDN URLs
    would be COEP-blocked) and the project rule is no external data flow. This
    is also what makes CJK / no-embedded-font PDFs render real glyphs.
  • Options: format (PNG / JPEG / WebP), resolution preset (72–600 DPI),
    page range (1-3, 5, 8-), and a quality slider for lossy formats.
  • JPEG/WebP get a white matte before encode (transparent regions would
    otherwise come out black). Pages render sequentially with the canvas
    released between pages (a 50-page export won't OOM); canvas dims are clamped
    to browser limits. Scripting/XFA stay off → embedded PDF JavaScript never runs.
  • Download per page or all as a ZIP (fflate, stored — images are
    already compressed).
  • i18n added to both en and zh-CN. Command palette + home grid pick it
    up automatically from the tool registry.

Verification

  • pnpm typecheck / lint / build green; pnpm test 393 passing (7 new
    for the page-range parser).
  • Headless Chrome against pnpm preview (real COOP/COEP headers) on a 3-page
    CJK PDF: crossOriginIsolated: true, all pages rendered at correct
    150-DPI dims with color + Chinese glyphs, JPEG corner [255,255,255]
    (white matte confirmed), zero external requests from pdf.js, no console
    errors.

Notes

  • public/pdfjs/ is ~4 MB of versioned pdf.js runtime assets, committed so
    prod is self-contained. src/lib/pdf.ts documents the re-copy step on
    pdfjs-dist upgrades.
  • Structured so sibling directions (image → PDF, etc.) and sibling tools slot
    in later under the same category.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XBhzzooAQNwaM4vg1CmpFo

New top-level "File Convert" category (sidebar + home grid) whose first
tool, "PDF Convert", rasterizes PDF pages to PNG / JPEG / WebP entirely
in the browser — no upload, no external calls.

- pdfjs-dist for rendering; worker bundled same-origin via ?url.
- cmaps / standard_fonts / wasm served from public/pdfjs/ (not a CDN) so
  CJK + no-embedded-font PDFs render and cross-origin isolation / the
  no-external-calls rule both hold.
- Per-page format, DPI preset (72–600), page-range parser (1-3,5,8-),
  JPEG/WebP quality slider. JPEG/WebP get a white matte (no black alpha).
- Sequential render + eager canvas release (multi-page won't OOM);
  canvas dims clamped to browser limits. Scripting/XFA left off, so
  embedded PDF JavaScript never runs.
- Per-page + ZIP (fflate, stored) download. i18n in en + zh-CN.
- Unit tests for the page-range parser (7 cases).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XBhzzooAQNwaM4vg1CmpFo
@lyfuci lyfuci merged commit 69c3021 into main Jul 9, 2026
2 checks passed
@lyfuci lyfuci deleted the feat/pdf-to-image branch July 9, 2026 02:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant