Skip to content

Releases: phant0um/pdf2md

v0.6.0 — CLI/GUI reparados, ligaduras, Keychain estável

Choose a tag to compare

@phant0um phant0um released this 24 Sep 16:39
2b39c7c

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_md para de embutir base64 por
    padrão (decisão D2) e passa a respeitar --imagens — extrair grava
    assets com posição preservada no documento, ambos usa OCR como
    alt-text, ignorar descarta. Maquinaria de segurança compartilhada via
    core/image_assets.py (dedup, nomenclatura, limites, symlink).
    core/pdf_images.py fica só com a parte PyMuPDF.

  • --imagens transcrever|extrair|ambos|ignorar (PDF-only): política de
    imagens embutidas. extrair salva os assets (default <stem>_assets/) e
    linka ![](...); ambos extrai e usa OCR como alt-text; ignorar
    descarta sem OCR; default transcrever é byte-idêntico ao atual.
    --assets-dir sobrescreve o diretório; --obsidian usa
    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.py com 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: BatchProcessor now
    injects PDF2MD_LLM_URL/MODEL/KEY into the process environment. Provider
    presets (Ollama, Gemini, Groq, OpenRouter, custom), live model list and
    connection status come from the new pdf2md llm subcommands; the API key
    is stored in the macOS Keychain (never in argv — ps aux safe).

  • CLI flags --llm-url / --llm-modelo with precedence flag > env >
    default, propagated cli → batch → quality → llm_enhancer via ConfigLLM.

  • 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) e limpar_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_md extraí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.document sem officedocument.);
    filtro agora é por extensão, espelhando EXTENSOES_PERMITIDAS do 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_fffd separa 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=False quando o engine de layout está ativo. O projeto já tem OCR
    próprio controlado por ModoImagem.

  • 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 .app não convertia (desde v0.4.0). O CLI exigia o
    subcomando converter, mas a GUI chamava pdf2md <arquivo> <destino> --json → "No such command". Default-command no entry point: a forma
    canônica pdf2md <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 propagava item.avisos; o ícone âmbar nunca aparecia (A1).

  • --imagens: crash em ambos com 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 --baseline auto-atualiza o
    baseline e sai 0 com segredo novo; --fail-on-unknown não existe no 1.5.0.
    Gate real: detect-secrets-hook + grep ERROR: Potential secrets (#29).

  • CI: smoke llm testar validava 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 testar are 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: testar importado 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

Choose a tag to compare

@phant0um phant0um released this 30 Jun 01:07
fcd189b

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

Choose a tag to compare

@phant0um phant0um released this 31 May 03:06
fd0896e

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

  1. Baixe PDF2MD-v0.4.0.dmg
  2. Arraste PDF2MD.app para Applications
  3. Primeira abertura: clique direito → Abrir (Gatekeeper bypass)
  4. 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/v1

pdf2md v0.3.1

Choose a tag to compare

@phant0um phant0um released this 30 May 03:28
62e9d54

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

  1. Baixe PDF2MD-v0.3.1.dmg, abra, arraste PDF2MD para Aplicativos
  2. Primeira execução: clique-direito → Abrir
  3. Para .doc/OCR: brew install antiword tesseract tesseract-lang

Requisitos: macOS 13+ · Apple Silicon (arm64)

SHA256: e40d181d152e951fd3265bddd666e5da3a32628f5e276fac5b1ce703f7b27ca4

pdf2md v0.3.0

Choose a tag to compare

@phant0um phant0um released this 30 May 03:13
53a6c03

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

  1. Baixe PDF2MD-v0.3.0.dmg, abra e arraste PDF2MD para Aplicativos
  2. Primeira execução: clique-direito → Abrir (assinatura ad-hoc)
  3. Para .doc e OCR:
    brew install antiword tesseract tesseract-lang
    

Requisitos: macOS 13+ · Apple Silicon (arm64)

SHA256: 3c8177fa6c93ec243a508f2f5100f44c40be0c97e8494fbed57c0ab4ada5cc64

pdf2md v0.2.0

Choose a tag to compare

@phant0um phant0um released this 30 May 01:39
0093c5b

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.docx colidiam no mesmo .md
  • Deadlock da GUI (leitura de pipe após término do processo)
  • .doc PT-BR com acentos (encoding Latin-1 do antiword)

Changelog completo: CHANGELOG.md

Instalação

  1. Baixe PDF2MD-v0.2.0.dmg abaixo, abra e arraste PDF2MD para Aplicativos
  2. Primeira execução: clique-direito → Abrir (assinatura ad-hoc, bypass do Gatekeeper)
  3. 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 Pre-release
Pre-release

Choose a tag to compare

@phant0um phant0um released this 29 May 21:35

pdf2md v0.1.0

Converte PDFs e imagens em Markdown. Suporte a batch e integração com Obsidian vault.

Instalação

  1. Baixe PDF2MD-v0.1.0.dmg
  2. Abra o DMG e arraste PDF2MD.app para Applications
  3. Primeira abertura: clique com botão direito → Abrir (Gatekeeper bypass — app não assinado com conta paga)
  4. 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-michel

Formatos 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