fix(project-manager): remover Dify KB das descriptions, marcar nota TODO
Dify foi removido 06-03-2026. Skills brainstorm/discover ainda referenciam-no no corpo. Bump v1.2 + nota top-of-file. Reescrita workflow para próxima sessão. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
---
|
||||
name: pdf
|
||||
description: Processamento de ficheiros PDF — leitura, extracção, merge, split, OCR, formulários. Versão light para heartbeats.
|
||||
---
|
||||
|
||||
# PDF — Referência Rápida
|
||||
|
||||
## Bibliotecas Python
|
||||
|
||||
### pypdf — operações básicas
|
||||
|
||||
```python
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
|
||||
# Ler e extrair texto
|
||||
reader = PdfReader("documento.pdf")
|
||||
for page in reader.pages:
|
||||
text = page.extract_text()
|
||||
|
||||
# Merge
|
||||
writer = PdfWriter()
|
||||
for pdf in ["doc1.pdf", "doc2.pdf"]:
|
||||
for page in PdfReader(pdf).pages:
|
||||
writer.add_page(page)
|
||||
with open("merged.pdf", "wb") as f:
|
||||
writer.write(f)
|
||||
|
||||
# Split (uma página por ficheiro)
|
||||
for i, page in enumerate(reader.pages):
|
||||
w = PdfWriter()
|
||||
w.add_page(page)
|
||||
with open(f"page_{i+1}.pdf", "wb") as f:
|
||||
w.write(f)
|
||||
|
||||
# Rotate
|
||||
page = reader.pages[0]
|
||||
page.rotate(90)
|
||||
|
||||
# Password
|
||||
writer.encrypt("userpass", "ownerpass")
|
||||
```
|
||||
|
||||
### pdfplumber — tabelas e texto com layout
|
||||
|
||||
```python
|
||||
import pdfplumber
|
||||
|
||||
with pdfplumber.open("doc.pdf") as pdf:
|
||||
for page in pdf.pages:
|
||||
text = page.extract_text()
|
||||
tables = page.extract_tables()
|
||||
```
|
||||
|
||||
### reportlab — criação de PDFs
|
||||
|
||||
```python
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle, PageBreak
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
from reportlab.lib import colors
|
||||
|
||||
doc = SimpleDocTemplate("report.pdf")
|
||||
styles = getSampleStyleSheet()
|
||||
elements = [Paragraph("Título", styles['Title'])]
|
||||
doc.build(elements)
|
||||
```
|
||||
|
||||
**Subscripts/superscripts:** Nunca usar caracteres Unicode. Usar tags XML: `<sub>2</sub>`, `<super>2</super>`.
|
||||
|
||||
## CLI
|
||||
|
||||
```bash
|
||||
# Extrair texto (poppler-utils)
|
||||
pdftotext input.pdf output.txt
|
||||
pdftotext -layout input.pdf output.txt
|
||||
|
||||
# Merge/split (qpdf)
|
||||
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf
|
||||
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf
|
||||
|
||||
# Encriptar
|
||||
qpdf --encrypt user_pass owner_pass 256 -- input.pdf encrypted.pdf
|
||||
|
||||
# Reparar
|
||||
qpdf --check input.pdf
|
||||
|
||||
# Extrair imagens
|
||||
pdfimages -j input.pdf output_prefix
|
||||
|
||||
# Render para PNG
|
||||
pdftoppm -png -r 300 document.pdf output_prefix
|
||||
```
|
||||
|
||||
## OCR (PDFs digitalizados)
|
||||
|
||||
```python
|
||||
import pytesseract
|
||||
from pdf2image import convert_from_path
|
||||
|
||||
images = convert_from_path('scanned.pdf')
|
||||
text = ""
|
||||
for image in images:
|
||||
text += pytesseract.image_to_string(image)
|
||||
```
|
||||
|
||||
## Formulários
|
||||
|
||||
### Verificar campos preenchíveis
|
||||
|
||||
```bash
|
||||
python scripts/check_fillable_fields.py <file.pdf>
|
||||
```
|
||||
|
||||
### Campos preenchíveis (nativos)
|
||||
|
||||
1. `python scripts/extract_form_field_info.py <input.pdf> <field_info.json>`
|
||||
2. `python scripts/convert_pdf_to_images.py <file.pdf> <output_dir>`
|
||||
3. Criar `field_values.json` com `field_id`, `page`, `value`
|
||||
4. `python scripts/fill_fillable_fields.py <input.pdf> <field_values.json> <output.pdf>`
|
||||
|
||||
### Campos não preenchíveis (anotações)
|
||||
|
||||
1. `python scripts/extract_form_structure.py <input.pdf> form_structure.json`
|
||||
2. **Abordagem A (estrutura):** Analisar JSON, criar `fields.json` com `pdf_width`/`pdf_height` e bounding boxes
|
||||
3. **Abordagem B (visual):** Converter para imagens, identificar campos, refinar com crop
|
||||
4. `python scripts/check_bounding_boxes.py fields.json`
|
||||
5. `python scripts/fill_pdf_form_with_annotations.py <input.pdf> fields.json <output.pdf>`
|
||||
6. `python scripts/create_validation_image.py <page> <fields.json> <input_img> <output_img>`
|
||||
|
||||
## Referência rápida
|
||||
|
||||
| Tarefa | Ferramenta | Comando |
|
||||
|--------|-----------|---------|
|
||||
| Merge | pypdf/qpdf | `writer.add_page()` / `qpdf --pages` |
|
||||
| Split | pypdf/qpdf | Uma página por ficheiro |
|
||||
| Texto | pdfplumber | `page.extract_text()` |
|
||||
| Tabelas | pdfplumber | `page.extract_tables()` |
|
||||
| Criar | reportlab | Canvas ou Platypus |
|
||||
| OCR | pytesseract | Converter para imagem primeiro |
|
||||
| Formulários | pypdf/scripts | Ver secção acima |
|
||||
|
||||
## Caminhos Descomplicar
|
||||
|
||||
| Local | Caminho |
|
||||
|-------|---------|
|
||||
| Documentos empresa | `/media/ealmeida/Dados/GDrive/Cloud/Descomplicar/` |
|
||||
| Propostas | `/media/ealmeida/Dados/Hub/03-Propostas/` |
|
||||
| Arquivo clientes | `/media/ealmeida/Dados/GDrive/Arquivo_de_Clientes/` |
|
||||
| Knowledge Base | `/media/ealmeida/Dados/Hub/06-Operacoes/Knowledge-Base/PDFs/` |
|
||||
| Temporários | `~/.claude-work/` (limpar ao concluir) |
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Localizar PDF (filesystem ou Google Drive)
|
||||
2. Descarregar para `~/.claude-work/` se necessário
|
||||
3. Processar
|
||||
4. Guardar no destino final
|
||||
5. Limpar temporários
|
||||
|
||||
---
|
||||
**Versão**: 1.0.0-light | **Base**: 1.0.0
|
||||
Reference in New Issue
Block a user