Skip to content

Commit 44a47bf

Browse files
jorbenclaude
andauthored
docs: 📝 add CLAUDE.md for Claude Code guidance (#34)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 938af80 commit 44a47bf

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
MarkPDFdown Desktop is an Electron application that converts PDF/images to Markdown using LLM visual recognition. Built with Electron 38 + React 18 + TypeScript + Vite (via electron-vite) + Prisma (SQLite) + Ant Design 5.
8+
9+
## Commands
10+
11+
```bash
12+
# Development
13+
npm run dev # Generate Prisma client + start dev server
14+
15+
# Build
16+
npm run build # Generate Prisma client + production build
17+
npm run build:win # Build Windows NSIS installer
18+
npm run build:mac # Build macOS DMG
19+
npm run build:linux # Build Linux AppImage
20+
21+
# Testing (Vitest)
22+
npm test # Run all tests (watch mode)
23+
npm run test:unit # Unit tests only (main process + core, node env)
24+
npm run test:renderer # Component tests only (React, jsdom env)
25+
npm run test:watch # Watch mode
26+
npm run test:coverage # Coverage report
27+
28+
# Single test file
29+
npx vitest run path/to/file.test.ts --config vitest.config.ts # unit test
30+
npx vitest run path/to/file.test.tsx --config vitest.config.renderer.ts # renderer test
31+
32+
# Database
33+
npm run generate # Generate Prisma client
34+
npm run migrate:dev # Run migrations (dev)
35+
36+
# Code quality
37+
npm run lint # ESLint with auto-fix
38+
npm run typecheck # TypeScript type checking
39+
```
40+
41+
## Architecture
42+
43+
### Three-process Electron structure
44+
45+
- **Main process** (`src/main/`): Window management, IPC handler registration, app lifecycle
46+
- **Preload** (`src/preload/`): Secure bridge exposing `window.api` to renderer
47+
- **Renderer** (`src/renderer/`): React SPA with Ant Design, HashRouter routing
48+
49+
### Core business logic (`src/core/`) — Clean Architecture
50+
51+
```
52+
core/
53+
├── domain/ # Interfaces only: ILLMClient, ISplitter, repositories
54+
├── application/ # Business logic orchestration
55+
│ ├── services/ # WorkerOrchestrator, ModelService, PresetProviderService
56+
│ └── workers/ # WorkerBase (abstract), SplitterWorker, ConverterWorker, MergerWorker
57+
├── infrastructure/ # External implementations
58+
│ ├── db/ # Prisma schema, migrations, client
59+
│ ├── adapters/
60+
│ │ ├── llm/ # OpenAIClient, AnthropicClient, GeminiClient, OllamaClient, OpenAIResponsesClient
61+
│ │ └── split/ # PDFSplitter, ImageSplitter, SplitterFactory
62+
│ └── services/ # FileService
63+
└── shared/events/ # EventBus for worker coordination
64+
```
65+
66+
### IPC communication pattern
67+
68+
All main-process handlers are in `src/main/ipc/handlers/` and return `{ success: boolean, data?: T, error?: string }`. Renderer calls via `window.api.*` exposed through preload.
69+
70+
### Worker pipeline
71+
72+
PDF conversion follows a three-stage pipeline managed by `WorkerOrchestrator`:
73+
1. **SplitterWorker** — Splits PDF/images into per-page PNGs
74+
2. **ConverterWorker** — Sends each page image to LLM for Markdown conversion
75+
3. **MergerWorker** — Merges converted pages into final Markdown
76+
77+
Workers extend `WorkerBase` which provides graceful shutdown and lifecycle hooks.
78+
79+
### Shared types (`src/shared/`)
80+
81+
IPC channel definitions and shared TypeScript types used by both main and renderer processes.
82+
83+
## Key Conventions
84+
85+
- **ESM modules** throughout (`"type": "module"` in package.json)
86+
- **Path alias**: `@` maps to `src/renderer/` in renderer code; `@` maps to `src/` in test configs
87+
- **Preload is CJS**: Preload scripts build to CommonJS format despite the rest being ESM
88+
- **Prisma schema** lives at `src/core/infrastructure/db/schema.prisma` — all migration/generate commands reference this path
89+
- **`no-explicit-any` is disabled** in ESLint config
90+
- **i18n**: 6 locales in `src/renderer/locales/` (en-US, zh-CN, ja-JP, ru-RU, ar-SA, fa-IR)
91+
- **Commit style**: Conventional commits (feat, fix, chore, etc.) with emoji prefixes
92+
- **Pre-commit**: Husky + lint-staged runs ESLint and Prettier
93+
94+
## Testing
95+
96+
Two separate Vitest configs:
97+
- `vitest.config.ts` — Node environment for `src/main/`, `src/core/`, `src/preload/`
98+
- `vitest.config.renderer.ts` — jsdom environment for `src/renderer/` (has retry=2 and 10s timeout for async tests)
99+
100+
Test helpers in `tests/`:
101+
- `tests/setup.ts` — Mocks Electron, electron-is-dev, global.fetch
102+
- `tests/setup.renderer.ts` — Renderer test setup
103+
- `tests/helpers/` — Database helpers, IPC mocks, LLM mocks, window API mocks
104+
- `tests/fixtures/` — JSON fixture data
105+
106+
## Database
107+
108+
SQLite via Prisma with 4 models: Provider, Model, Task, TaskDetail. Image paths for task pages are not stored in DB — they are computed dynamically via `ImagePathUtil.getPath(task, page)` as `{tempDir}/{taskId}/page-{page}.png`.

0 commit comments

Comments
 (0)