Thanks for considering a contribution. JDF is a small but ambitious project — every PR matters.
git clone https://github.com/uurtech/jdf.git
cd jdf
pnpm install
pnpm dev # frontend hot-reload (Vite)
pnpm tauri # full desktop appPrerequisites:
- Node.js 20+
- pnpm 9+
- Rust (latest stable)
- macOS: Xcode Command Line Tools
spec/ — JSON Schema + example .jdf files
packages/jdf-core/ — shared TypeScript types
apps/reader/ — Tauri v2 desktop app
src/ — SolidJS frontend
src-tauri/ — Rust backend (PDF/MD parse, export)
tools/jdf-cli/ — validate/import CLI
- Type-check everything:
pnpm typecheck(coversapps/readerandtools/jdf-cli). - Compile Rust:
cd apps/reader/src-tauri && cargo check. - Validate the spec changes round-trip: if you've touched the format, run
pnpm --filter @uurtech/jdf-cli start validate spec/examples/hello-world.jdfand make sure it still passes. - Keep the diff focused. One feature or fix per PR.
- Don't commit
.DS_Store,dist/,target/, or anything in.gitignore.
Easy:
- New element renderer styles, edge cases in tables/lists.
- More example
.jdffiles inspec/examples/. - Better PDF import heuristics (
apps/reader/src-tauri/src/commands/mod.rs::text_to_jdf).
Medium:
- PDF export improvements (image embed, multi-page overflow, TOC pagination).
- Element insertion/deletion in the visual editor.
- VS Code extension scaffolding.
Hard / planned:
- WYSIWYG editor for element structure (insert / move / delete).
- True image extraction from PDF (
pdf-extractonly gives text). - Windows/Linux build & GitHub Actions CI/CD.
- Web-based viewer (
apps/web).
If you change the JDF format itself:
- Update
packages/jdf-core/src/types.ts. - Update
spec/jdf-schema.jsonto match. - Bump the
$jdfversion inspec/examples/hello-world.jdfand document the breaking change. - Update the relevant renderer in
apps/reader/src/components/viewer/. - Update
apps/reader/src-tauri/src/commands/mod.rs(searchextract_text,export_pdf). - Add an example to
spec/examples/.
- TypeScript: strict mode, no
anyunless necessary. - SolidJS: prefer
createSignal+createMemo; avoid effects for derived state. - Rust:
cargo fmt, idiomatic error handling with?andResult<_, String>for Tauri commands. - Keep components small. The
viewer/element renderers should stay <100 lines each.
By contributing you agree your code will ship under the MIT License.