Repository navigation
Releases: phant0um/pdf2md
Release list
v0.6.0 — CLI/GUI reparados, ligaduras, Keychain estável
Added
-
Presets de LLM: OpenCode Zen (
https://opencode.ai/zen/v1), OpenCode
Go (https://opencode.ai/zen/go/v1) e Ollama Cloud
(https://ollama.com/v1) no fallback de qualidade — GUI (picker de
provider), docstring de env do CLI e README (#32). -
DOCX unificado com o PDF (T19):
doc_to_mdpara de embutir base64 por
padrão (decisão D2) e passa a respeitar--imagens—extrairgrava
assets com posição preservada no documento,ambosusa OCR como
alt-text,ignorardescarta. Maquinaria de segurança compartilhada via
core/image_assets.py(dedup, nomenclatura, limites, symlink).
core/pdf_images.pyfica só com a parte PyMuPDF. -
--imagens transcrever|extrair|ambos|ignorar(PDF-only): política de
imagens embutidas.extrairsalva os assets (default<stem>_assets/) e
linka;ambosextrai e usa OCR como alt-text;ignorar
descarta sem OCR; defaulttranscreveré byte-idêntico ao atual.
--assets-dirsobrescreve o diretório;--obsidianusa
vault/attachments/com wikilinks![[...]]. -
Segurança de extração (ADR-0005): nomes sempre gerados (nunca do
metadado do PDF), dedup por SHA-256, limites anti resource-bomb (500
imagens/documento, 50 MB/imagem), recusa de symlink no assets dir, ext
exótica normalizada para PNG. -
core/pdf_images.pycom 8 testes (extração, dedup, limites, nome
hostil, symlink, PDF sem imagem). -
ADR-0005: decisões D1–D5 (destino, base64 rejeitado, render de scan,
dedup, nomenclatura). -
LLM provider/model picker in the GUI (Settings window) — fixes the
silent no-op of the AI Enhance toggle in the.app:BatchProcessornow
injectsPDF2MD_LLM_URL/MODEL/KEYinto the process environment. Provider
presets (Ollama, Gemini, Groq, OpenRouter, custom), live model list and
connection status come from the newpdf2md llmsubcommands; the API key
is stored in the macOS Keychain (never in argv —ps auxsafe). -
CLI flags
--llm-url/--llm-modelowith precedence flag > env >
default, propagatedcli → batch → quality → llm_enhancerviaConfigLLM. -
pdf2md llm modelos --json— lists models from the endpoint, with
vision capability detection for local Ollama (/api/show). -
pdf2md llm testar --json— uncached connectivity probe with latency
measurement; failure returns{"ok": false}with exit 0 (JSON is the GUI
contract, no traceback). -
ADR-0007: LLM config decisions D6–D10 (Keychain, env injection, SSRF
by design, keychain/ad-hoc signing limitation).
Changed
- Desempenho do pipeline de qualidade:
corrigir_mojibake(~40 travessias
O(n) de count+replace) elimpar_artefatos(6× replace) agora rodam em
1 passada (regex sub + str.translate compilada) (#30). - Tabela do CLI determinística: resultados em batch seguem a ordem de
entrada (antes: ordem de conclusão do ThreadPool, variava entre runs) (#30). _linha_tabela_mdextraído (DRY pptx/xlsx) (#30).- GUI: drop/picker aceitam .docx, .pptx e .xlsx de novo — o filtro por
UTI hardcoded nunca casava com a resolução do LaunchServices (docx →
org.openxmlformats.wordprocessingml.documentsemofficedocument.);
filtro agora é por extensão, espelhandoEXTENSOES_PERMITIDASdo core (#31).
Fixed
-
Aviso falso de "texto corrompido" em PDF com fórmula (BAIXA): glifo de
fórmula sem ToUnicode (Σ,=de fontes TeX como pxfonts) gerava o aviso
"texto provavelmente corrompido por problema de encoding", mas as palavras
estavam intactas.classificar_fffdsepara os U+FFFD: colado em letra de
texto corrido continua como encoding corrompido; fora de palavra (vizinho
de espaço, colchete, letra grega ou letra matemática) vira aviso próprio,
"símbolo(s) sem mapeamento Unicode … revise as fórmulas". -
Ligaduras tipográficas (fl, fi, ff...) viravam U+FFFD na conversão (MÉDIA):
o engine de layout do pymupdf4llm mapeia glifos de ligadura para U+FFFD quando
a fonte embutida não traz ToUnicode — "Workflow" saía como "Work�ow" e
"reflect" como "re�ect". Reparo por dicionário do próprio documento:
page.get_text()como referência, substituição 1-para-1, sem adivinhação.
Limitação: FFFD de fonte matemática (Σ, ∫) não tem referência no texto cru e
continua avisado. -
OCR interno do pymupdf4llm duplicava trabalho (~40% do tempo de extração):
use_ocr=Falsequando o engine de layout está ativo. O projeto já tem OCR
próprio controlado porModoImagem. -
Assets com espaço/acento no nome quebravam
--obsidian/--assets-dir
(ALTA): o prefixo{stem}__com "Relatório.pdf" violava o regex de nome
seguro → ValueError → arquivo inteiro virava ERRO. Prefixo agora passa por
slugify ASCII (NFKD). Revisão fullstack 2026-08-13 (#29). -
DOCX com imagem gigante derrubava o processo (ALTA):
f.read()lia a
imagem inteira antes do check de 50 MB — docx malicioso de 2 GB causava OOM.
Tamanho agora é checado via seek/tell antes da leitura (#29). -
GUI: erros do subprocesso invisíveis — stderr era descartado e exit code
nunca verificado; todo erro virava "Falha ao executar processo". ProcessRunner
agora propaga (stdout, stderr, exitCode) e a GUI exibe o erro real (#29). -
Default-command com flags antes do positional (
pdf2md --sobrescrever in.pdf out/) falhava com "No such option" — flags são reordenadas (#29). -
Markup Rich vazava no JSON
erro([red]...[/red]renderizado cru na GUI)
— mensagem limpa no caminho--json(#29). -
XLSX com linhas vazias no topo descartava o conteúdo — primeira linha
não-vazia vira header; streaming read_only preservado (2 passadas) (#29). -
TesseractError mascarado como "arquivo corrompido" — mensagem real de OCR
(idioma ausente) agora é exibida (#29). -
CLI/GUI: o
.appnão convertia (desde v0.4.0). O CLI exigia o
subcomandoconverter, mas a GUI chamavapdf2md <arquivo> <destino> --json→ "No such command". Default-command no entry point: a forma
canônicapdf2md <origem> [destino] [opções]agora funciona (a explícita
pdf2md converter ...continua). Auditado por Grok 4.5 max (C1). -
GUI: avisos de qualidade eram descartados —
atualizarProgresso
não propagavaitem.avisos; o ícone âmbar nunca aparecia (A1). -
--imagens: crash emamboscom GIF/PPM (ocr_bytes normaliza para
PNG); renders de scan contam no limite anti bomb; colisão de stem
em dirs de assets compartilhados (prefixo pelo stem do .md destino) —
fixes da Emenda 2 do ADR-0005 (#22/cf9ab44).
Security
-
CI: gate detect-secrets era vácuo —
scan --baselineauto-atualiza o
baseline e sai 0 com segredo novo;--fail-on-unknownnão existe no 1.5.0.
Gate real:detect-secrets-hook+ grepERROR: Potential secrets(#29). -
CI: smoke
llm testarvalidava valor, não contrato — sem servidor no CI,
ok: falseé legítimo; gate agora valida o shape JSON ("ok": true|false). -
CI:
permissions: contents: read(least privilege) + actions pinadas por
SHA (checkout v4.4.0, setup-python v5.6.0, setup-uv v5.4.2, cache v4.3.0). -
mypy strict agora roda no CI — config existia mas estava morta; 21 erros
resolvidos (anotações + ignore_missing_imports para libs sem stubs). -
Prompt injection documentado em SECURITY.md (texto do documento vai ao
LLM sem isolamento — risco aceito, ADR-0004). -
Error messages from
llm modelos/llm testarare sanitized (CWE-209/532):
only HTTP code or failure category is exposed, never URL/path/credential. -
API key is transmitted only via
process.environment(D8) and the
Authorization header — never through argv or JSON output. -
Image extraction hardening (ADR-0005): path traversal, symlink and
resource-bomb mitigations with tests proving each one.
Testes
- 206 → 273 testes; cobertura 87% → 94% (cli.py 68→88%, image_converter
75→95%, pdf_images 79→100%) (#29, #30). - Teste-fantasma corrigido:
testarimportado de llm_enhancer fazia
chamada de rede real a localhost:11434 na suíte — renomeado para_testar_llm.
Instalação
- Build Apple Silicon (arm64), macOS 13+. OCR requer Tesseract:
brew install tesseract tesseract-lang. - App sem notarização: na primeira execução, botão direito → Abrir.
- SHA-256 de
PDF2MD-v0.6.0.dmg:a2c983888e5927de3159ce1c925acc300fa88802afef435bd71112ae09e86d1e
v0.5.0 — --ignorar-margens, OCR vision fallback, 5E score 93/100
What's new
Added
--ignorar-margens N: Remove page headers and footers from PDF output.
Filters text blocks by vertical bbox position — N% of page height from top and bottom.
Example:pdf2md doc.pdf output/ --ignorar-margens 5- OCR vision fallback: When Tesseract returns <10 chars, automatically tries
LLM vision (Ollama/Gemini) if available. Handles unusual fonts, manuscripts.
Removed
- Per-file duration: No more per-file time in CLI table or JSON output.
Only total conversion time is shown.
Changed
- Forge 5E score: 79 → 93/100 (production-ready)
- 142 tests (was 103), ruff clean, CI green
- DRY helpers, function splits, magic numbers named, compiled regex, lazy imports
- GUI Swift synced (removed per-file duration display)
- Bundle ID:
com.mchlcs→com.phant0um
Security
- Sentinel: PASS (CWE-209, CWE-918, CWE-532, path traversal, subprocess safety)
Download
PDF2MD-v0.5.0.dmg — 85MB, arm64, macOS 13+
SHA256: c4bb40a65bb4f135152f3a20166d105d943b914ae30a988370d5b8d3aac11f4b
v0.4.0 — PPTX, XLSX, CSV, qualidade e LLM fallback
Novidades
Novos formatos
- PPTX — slides, títulos, tabelas → Markdown
- XLSX — cada sheet vira tabela Markdown
- CSV — suporte a BOM, UTF-8, Latin-1 (exports PT-BR)
Pipeline de qualidade automático
- Corrige mojibake PT-BR (ã, ç, é, etc.) automaticamente
- Remove hifens suaves (U+00AD), zero-width chars, BOM mid-string
- Avisos ⚠ no CLI e GUI quando qualidade baixa
LLM fallback (Ollama / Gemini / Groq)
--llm-fallback: usa LLM local quando qualidade baixa- Funciona com Ollama (grátis, local) ou qualquer API OpenAI-compatible
- Toggle "⚡ Melhorar com IA" na GUI
- Zero deps extras — usa urllib stdlib
GUI melhorada
- Botão Procurar arquivos… — abre seletor multi-format
- Colar imagem — cola do clipboard direto na fila
- Toggle ⚡ Melhorar com IA — LLM fallback automático
- Ícone âmbar para conversões com avisos de qualidade
13 bugs corrigidos (code review max-effort)
Ver CHANGELOG.md para lista completa.
Instalação
- Baixe
PDF2MD-v0.4.0.dmg - Arraste PDF2MD.app para Applications
- Primeira abertura: clique direito → Abrir (Gatekeeper bypass)
- Instale Tesseract:
brew install tesseract tesseract-lang
LLM fallback (opcional)
brew install ollama
ollama pull llama3.2-vision
export PDF2MD_LLM_URL=http://localhost:11434/v1pdf2md v0.3.1
Patch: corrige o tempo por-arquivo que aparecia sempre "0.0s".
Correção
- Tempo por-arquivo "0.0s": conversões de texto levam milissegundos, e o formatador arredondava tudo abaixo de 0.05s para "0.0s". Agora exibe em ms (ex:
125ms,230ms). A medição sempre esteve correta — só o display truncava. Afeta app e CLI.
O tempo total da tarefa já existia ("Concluído em Xs" no app, "Tempo:" no CLI) e também passa a exibir sub-segundo corretamente.
Licenças
O .app agora inclui LICENSE + THIRD-PARTY-LICENSES.md. Código pdf2md é MIT; o binário embarca PyMuPDF (AGPL-3.0) — ver THIRD-PARTY-LICENSES.md.
Changelog: CHANGELOG.md
Instalação
- Baixe
PDF2MD-v0.3.1.dmg, abra, arraste PDF2MD para Aplicativos - Primeira execução: clique-direito → Abrir
- Para
.doc/OCR:brew install antiword tesseract tesseract-lang
Requisitos: macOS 13+ · Apple Silicon (arm64)
SHA256: e40d181d152e951fd3265bddd666e5da3a32628f5e276fac5b1ce703f7b27ca4
pdf2md v0.3.0
Corrige a conversão de .doc no app empacotado + adiciona tempo de conversão.
⚠️ Se você usa a v0.2.0 e deu erro "antiword não encontrado" ao converter.doc, atualize — esta versão corrige.
Correções
- antiword não encontrado no
.doc: o app empacotado não achava o antiword (PATH mínimo do binário não inclui/opt/homebrew/bin/), mesmo instalado. Agora resolve o caminho explícito — mesmo fix que o Tesseract recebeu. - stdout poluído no modo
--json: ruído nativo do MuPDF era misturado ao protocolo do app; agora o stdout fica limpo.
Novidade
- Tempo de conversão: duração por arquivo + total. No app (lista + "Concluído em Xs" + notificação) e no CLI (coluna "Tempo").
Changelog: CHANGELOG.md
Instalação
- Baixe
PDF2MD-v0.3.0.dmg, abra e arraste PDF2MD para Aplicativos - Primeira execução: clique-direito → Abrir (assinatura ad-hoc)
- Para
.doce OCR:brew install antiword tesseract tesseract-lang
Requisitos: macOS 13+ · Apple Silicon (arm64)
SHA256: 3c8177fa6c93ec243a508f2f5100f44c40be0c97e8494fbed57c0ab4ada5cc64
pdf2md v0.2.0
PDF, imagens e documentos Word → Markdown, com OCR e integração Obsidian.
⚠️ Substitui a v0.1.0, que tinha um bug que impedia o Tesseract de ser encontrado no app empacotado. Atualize.
Novidades
- Suporte a Word:
.docx(mammoth) e.doc(antiword) - Botão Cancelar na GUI (cancelamento cooperativo)
- Campo de caminho unificado (saída ou vault Obsidian)
- Ícone do app
Correções principais
- Tesseract não encontrado no binário PyInstaller (o bug da v0.1.0)
- Perda de dados:
report.pdf+report.docxcolidiam no mesmo.md - Deadlock da GUI (leitura de pipe após término do processo)
.docPT-BR com acentos (encoding Latin-1 do antiword)
Changelog completo: CHANGELOG.md
Instalação
- Baixe
PDF2MD-v0.2.0.dmgabaixo, abra e arraste PDF2MD para Aplicativos - Primeira execução: clique-direito → Abrir (assinatura ad-hoc, bypass do Gatekeeper)
- Para OCR, instale o Tesseract:
brew install tesseract tesseract-lang
Requisitos: macOS 13+ · Apple Silicon (arm64)
SHA256: 9034aa944f2379b3e779518e4d0b40a65c6c061cd4dffe331be096cb4d675108
pdf2md v0.1.0
pdf2md v0.1.0
Converte PDFs e imagens em Markdown. Suporte a batch e integração com Obsidian vault.
Instalação
- Baixe
PDF2MD-v0.1.0.dmg - Abra o DMG e arraste PDF2MD.app para Applications
- Primeira abertura: clique com botão direito → Abrir (Gatekeeper bypass — app não assinado com conta paga)
- Instale Tesseract:
brew install tesseract tesseract-lang
CLI (alternativa)
# Extrai o binário do .app
cp /Applications/PDF2MD.app/Contents/Resources/pdf2md /usr/local/bin/pdf2md
pdf2md arquivo.pdf saida/
pdf2md pasta/ saida/ --workers 8 --obsidian
pdf2md docs/ --vault ~/Obsidian/vault-michelFormatos suportados
PDF, PNG, JPG, JPEG, TIFF, WEBP, BMP, HEIC
Obsidian integration
--vault PATH → output em vault/_inbox/ com frontmatter YAML automático:
---
title: nome-do-arquivo
source: original.pdf
converted: 2026-05-29
tags:
- pdf2md
- converted
---Requisitos
- macOS 13+
- Tesseract:
brew install tesseract tesseract-lang