v0.3.0 — automatic trilingual OCR, pure-Markdown output
What's changed since v0.2.3
- ci(web): add Lighthouse budgets (#106) by @alucard210319
- ci: add Codecov coverage upload (#107) by @0exec
- feat(api): optional Tesseract pre-pass for scanned PDFs (#86) by @0exec
- fix(web): use descriptive PDF preview iframe title (#87) by @zhouzhou626
- feat(web): implement dark mode theme (#75) by @GiulianaCDA
🚀 Features
- feat(ocr): enable OCR by default when the Tesseract stack is installed (#207) by @vinicq
- feat(ocr): default to eng+por+spa so OCR auto-handles EN/PT/ES (#199) (#203) by @vinicq
- feat(converter): detect and emit GFM strikethrough (#142) (#201) by @vinicq
- feat(web): add a download-all zip button to BatchPanel (closes #137) (#190) by @vinicq
- feat(web): make the needs_ocr warning prominent and handle ocr_required (closes #139) (#185) by @vinicq
- feat(api): block scanned PDFs with 422 ocr_required (part of #139) (#183) by @vinicq
- feat(web): honor prefers-reduced-motion globally (#132) by @vinicq
- feat(web): add global focus-visible ring with theme tokens (#130) by @vinicq
- feat(api): detect code blocks in pdf-to-md (#110) by @vinicq
- feat(ci): auto-update branches of stale auto-merge PRs (#85) by @vinicq
- feat(ci): auto-credit external contributors on PR merge (#80) by @vinicq
- feat(ci): auto-assign PR author when a pull request opens (#78) by @vinicq
- feat(ci): issue-claim Action with /claim and /take commands (#70) by @vinicq
🐛 Bug fixes
- fix(converter): stop a full-width rule being read as strikethrough (#202) (#210) by @vinicq
- fix(converter): nest a code block under its list item (#197) (#209) by @vinicq
- fix(converter): emit pure Markdown for small text and superscript (#141) (#200) by @vinicq
- fix(renderer): parse YAML front matter with safe_load (#150) (#198) by @vinicq
- fix(converter): keep multi-paragraph list items inside one item (#167) (#196) by @vinicq
- fix(converter): keep ordered lists contiguous instead of one item per paragraph (closes #144) (#193) by @vinicq
- fix(converter): escape literal Markdown punctuation in body text (closes #155) (#191) by @vinicq
- fix(api): silence MuPDF native stderr and route warnings to the logger (#180) by @vinicq
- fix(infra): stop nginx buffering large API responses to disk (#182) by @vinicq
- fix(web): time out and allow skipping stuck batch items (#179) by @vinicq
- fix(web): close color-contrast gaps across themes and locales (#131) by @vinicq
- fix(web): pause Toast auto-dismiss on hover and focus (#115) by @vinicq
- fix(ci): preserve existing contributor categories in credit workflow (#113) by @vinicq
- fix(ci): unblock board-sync and issue-claim workflows (#74) by @vinicq
📖 Documentation
- docs(changelog): cut v0.3.0 (#211) by @vinicq
- docs(deploy): dedicated Render free-tier walkthrough (#116) by @vinicq
- docs(contributing): document repository secrets (#103) by @vinicq
- docs(readme): link new MkDocs pages from the header (#102) by @vinicq
- docs: add deployment recipes page (#98) by @vinicq
- docs: add api recipes page (#97) by @vinicq
- docs: add faq page (#93) by @vinicq
- docs: add heuristics page (#92) by @vinicq
- docs(security): document new Pinned-Dependencies paths from #86 + Maintained (#90) by @vinicq
- docs: add architecture page to the MkDocs site (#79) by @vinicq
🔨 Maintenance
- chore(dev): portable backend interpreter + remove orphan pair log (#206) by @vinicq
- chore(deps): resync requirements files with pyproject (#205) by @vinicq
- chore(converter): resolve #144 review nits (#195) by @vinicq
- chore: ignore stray uv.lock (#189) by @vinicq
- chore(api): silence successful /api/health probes in the uvicorn access log (#181) by @vinicq
- chore(deps-ci): bump github/codeql-action from 4.35.5 to 4.36.0 (#122) by @dependabot[bot]
- chore(deps-ci): bump docker/build-push-action from 6.19.2 to 7.2.0 (#120) by @dependabot[bot]
- chore(deps-ci): bump docker/metadata-action from 5.10.0 to 6.1.0 (#124) by @dependabot[bot]
- chore(deps): bump nginx from
2f07d83to8b1e787in /apps/web (#119) by @dependabot[bot] - chore(deps): bump node from
e71ac5eto7c6af15in /apps/web (#118) by @dependabot[bot] - chore(deps-web): bump vite from 8.0.13 to 8.0.14 in /apps/web (#129) by @dependabot[bot]
- chore(deps-web): bump @types/node from 25.9.0 to 25.9.1 in /apps/web (#125) by @dependabot[bot]
- chore(deps-web): bump vitest from 4.1.6 to 4.1.7 in /apps/web (#126) by @dependabot[bot]
- chore(deps-web): bump typescript-eslint from 8.59.4 to 8.60.0 in /apps/web (#121) by @dependabot[bot]
- chore(ci): align dependabot commit prefixes with semantic-pr rules (#128) by @vinicq
- chore(deps-web): bump @types/react from 19.2.14 to 19.2.15 in /apps/web (#123) by @dependabot[bot]
- test(web): cross-browser Playwright matrix (Firefox + WebKit) (#117) by @vinicq
- chore(docs): credit @pink (#114) by @vinicq
- chore: pair log entry (#111) by @vinicq
- chore(docs): credit @alucard210319 (#108) by @vinicq
- chore(deploy): add render.yaml blueprint (#101) by @vinicq
- chore(docs): backfill changelog unreleased with 2026-05-22 work (#100) by @vinicq
- chore: remove orphan hook and unused social-preview asset (#91) by @vinicq
- chore(docs): credit 0exec for code+doc+test+infra on #86 (#89) by @vinicq
- chore(docs): credit zhouzhou626 for a11y on #87 (#88) by @vinicq
- chore: remove CONTRIBUTOR-WALKTHROUGH.md (#82) by @vinicq
- chore: explain empty except blocks to clear CodeQL py/empty-except (#84) by @vinicq
- chore(security): bump pypdf, markdown, python-multipart past 26 GHSAs (#83) by @vinicq
- chore(docs): credit @GiulianaCDA for the dark mode work (#81) by @vinicq
- chore(security): pin Docker base images to sha256 digest (#77) by @vinicq
- chore(security): pin Actions to SHA + scope workflow permissions (#76) by @vinicq
- chore(ci): mirror Projects v2 board workflows in a reviewable Action (#68) by @vinicq
Full changelog: v0.2.3...v0.3.0