feat: refactor 30+ skills to Anthropic progressive disclosure pattern
- All SKILL.md files now <500 lines (avg reduction 69%) - Detailed content extracted to references/ subdirectories - Frontmatter standardised: only name + description (Anthropic standard) - New skills: brand-guidelines, spec-coauthor, report-templates, skill-creator - Design skills: anti-slop guidelines, premium-proposals reference - Removed non-standard frontmatter fields (triggers, version, author, category) Plugins affected: infraestrutura, marketing, dev-tools, crm-ops, gestao, core-tools, negocio, perfex-dev, wordpress, design-media Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
512
dev-tools/skills/docx/SKILL.md
Normal file
512
dev-tools/skills/docx/SKILL.md
Normal file
@@ -0,0 +1,512 @@
|
||||
---
|
||||
name: docx
|
||||
description: "Criacao, edicao e analise de documentos Word (.docx). Usar quando o utilizador mencionar \"Word\", \".docx\", ou pedir documentos profissionais com formatacao (indices, cabecalhos, numeracao de paginas, letterheads). Inclui extracao de conteudo, insercao/substituicao de imagens, find-and-replace, tracked changes, comentarios, e conversao de conteudo para Word. Aplica-se a relatorios, memorandos, cartas, templates e propostas em formato .docx. NAO usar para PDFs, folhas de calculo, Google Docs, ou tarefas de codigo nao relacionadas."
|
||||
---
|
||||
|
||||
# Criacao, edicao e analise de documentos DOCX
|
||||
|
||||
## Visao geral
|
||||
|
||||
Um ficheiro .docx e um arquivo ZIP contendo ficheiros XML.
|
||||
|
||||
## Referencia rapida
|
||||
|
||||
| Tarefa | Abordagem |
|
||||
|--------|-----------|
|
||||
| Ler/analisar conteudo | `pandoc` ou descompactar para XML bruto |
|
||||
| Criar novo documento | Usar `docx-js` - ver seccao Criar Novos Documentos |
|
||||
| Editar documento existente | Descompactar -> editar XML -> recompactar - ver seccao Editar Documentos Existentes |
|
||||
|
||||
### Converter .doc para .docx
|
||||
|
||||
Ficheiros legacy `.doc` devem ser convertidos antes de editar:
|
||||
|
||||
```bash
|
||||
python scripts/office/soffice.py --headless --convert-to docx document.doc
|
||||
```
|
||||
|
||||
### Ler conteudo
|
||||
|
||||
```bash
|
||||
# Extracao de texto com tracked changes
|
||||
pandoc --track-changes=all document.docx -o output.md
|
||||
|
||||
# Acesso ao XML bruto
|
||||
python scripts/office/unpack.py document.docx unpacked/
|
||||
```
|
||||
|
||||
### Converter para imagens
|
||||
|
||||
```bash
|
||||
python scripts/office/soffice.py --headless --convert-to pdf document.docx
|
||||
pdftoppm -jpeg -r 150 document.pdf page
|
||||
```
|
||||
|
||||
### Aceitar tracked changes
|
||||
|
||||
Para produzir um documento limpo com todas as alteracoes aceites (requer LibreOffice):
|
||||
|
||||
```bash
|
||||
python scripts/accept_changes.py input.docx output.docx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Criar novos documentos
|
||||
|
||||
Gerar ficheiros .docx com JavaScript, depois validar. Instalacao: `npm install -g docx`
|
||||
|
||||
### Setup
|
||||
```javascript
|
||||
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
|
||||
Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
|
||||
TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,
|
||||
VerticalAlign, PageNumber, PageBreak } = require('docx');
|
||||
|
||||
const doc = new Document({ sections: [{ children: [/* conteudo */] }] });
|
||||
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));
|
||||
```
|
||||
|
||||
### Validacao
|
||||
Apos criar o ficheiro, validar. Se a validacao falhar, descompactar, corrigir o XML e recompactar.
|
||||
```bash
|
||||
python scripts/office/validate.py doc.docx
|
||||
```
|
||||
|
||||
### Tamanho da pagina
|
||||
|
||||
```javascript
|
||||
// CRITICO: docx-js assume A4 por defeito
|
||||
// Definir sempre o tamanho da pagina explicitamente para resultados consistentes
|
||||
// Para documentos PT/EU, A4 e o padrao correcto
|
||||
sections: [{
|
||||
properties: {
|
||||
page: {
|
||||
size: {
|
||||
width: 11906, // A4: 210mm em DXA
|
||||
height: 16838 // A4: 297mm em DXA
|
||||
},
|
||||
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1 polegada de margens
|
||||
}
|
||||
},
|
||||
children: [/* conteudo */]
|
||||
}]
|
||||
```
|
||||
|
||||
**Tamanhos de pagina comuns (unidades DXA, 1440 DXA = 1 polegada):**
|
||||
|
||||
| Papel | Largura | Altura | Largura conteudo (margens 1") |
|
||||
|-------|---------|--------|-------------------------------|
|
||||
| A4 (padrao PT/EU) | 11.906 | 16.838 | 9.026 |
|
||||
| US Letter | 12.240 | 15.840 | 9.360 |
|
||||
|
||||
**Orientacao paisagem:** docx-js troca largura/altura internamente, por isso passar dimensoes retrato e deixar a biblioteca tratar:
|
||||
```javascript
|
||||
size: {
|
||||
width: 11906, // Passar lado CURTO como width
|
||||
height: 16838, // Passar lado LONGO como height
|
||||
orientation: PageOrientation.LANDSCAPE // docx-js troca no XML
|
||||
},
|
||||
// Largura de conteudo = 16838 - margem esquerda - margem direita (usa o lado longo)
|
||||
```
|
||||
|
||||
### Estilos (Override Built-in Headings)
|
||||
|
||||
Usar Arial como fonte por defeito (suporte universal). Manter titulos a preto para legibilidade.
|
||||
|
||||
```javascript
|
||||
const doc = new Document({
|
||||
styles: {
|
||||
default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt por defeito
|
||||
paragraphStyles: [
|
||||
// IMPORTANTE: Usar IDs exactos para override dos estilos built-in
|
||||
{ id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
|
||||
run: { size: 32, bold: true, font: "Arial" },
|
||||
paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevel necessario para TOC
|
||||
{ id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
|
||||
run: { size: 28, bold: true, font: "Arial" },
|
||||
paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
|
||||
]
|
||||
},
|
||||
sections: [{
|
||||
children: [
|
||||
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Titulo")] }),
|
||||
]
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
### Listas (NUNCA usar bullets unicode)
|
||||
|
||||
```javascript
|
||||
// ERRADO - nunca inserir caracteres de bullet manualmente
|
||||
new Paragraph({ children: [new TextRun("* Item")] }) // MAU
|
||||
new Paragraph({ children: [new TextRun("\u2022 Item")] }) // MAU
|
||||
|
||||
// CORRECTO - usar config numbering com LevelFormat.BULLET
|
||||
const doc = new Document({
|
||||
numbering: {
|
||||
config: [
|
||||
{ reference: "bullets",
|
||||
levels: [{ level: 0, format: LevelFormat.BULLET, text: "\u2022", alignment: AlignmentType.LEFT,
|
||||
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
|
||||
{ reference: "numbers",
|
||||
levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
|
||||
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
|
||||
]
|
||||
},
|
||||
sections: [{
|
||||
children: [
|
||||
new Paragraph({ numbering: { reference: "bullets", level: 0 },
|
||||
children: [new TextRun("Item com bullet")] }),
|
||||
new Paragraph({ numbering: { reference: "numbers", level: 0 },
|
||||
children: [new TextRun("Item numerado")] }),
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
// ATENCAO: Cada reference cria numeracao INDEPENDENTE
|
||||
// Mesma reference = continua (1,2,3 depois 4,5,6)
|
||||
// Reference diferente = reinicia (1,2,3 depois 1,2,3)
|
||||
```
|
||||
|
||||
### Tabelas
|
||||
|
||||
**CRITICO: Tabelas precisam de larguras duplas** - definir tanto `columnWidths` na tabela COMO `width` em cada celula. Sem ambos, tabelas renderizam incorrectamente em algumas plataformas.
|
||||
|
||||
```javascript
|
||||
// CRITICO: Definir sempre largura da tabela para renderizacao consistente
|
||||
// CRITICO: Usar ShadingType.CLEAR (nao SOLID) para evitar fundos pretos
|
||||
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
|
||||
const borders = { top: border, bottom: border, left: border, right: border };
|
||||
|
||||
new Table({
|
||||
width: { size: 9026, type: WidthType.DXA }, // Sempre usar DXA (percentagens quebram no Google Docs)
|
||||
columnWidths: [4513, 4513], // Deve somar a largura da tabela (DXA: 1440 = 1 polegada)
|
||||
rows: [
|
||||
new TableRow({
|
||||
children: [
|
||||
new TableCell({
|
||||
borders,
|
||||
width: { size: 4513, type: WidthType.DXA }, // Tambem definir em cada celula
|
||||
shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR e nao SOLID
|
||||
margins: { top: 80, bottom: 80, left: 120, right: 120 }, // Padding da celula (interno, nao adicionado a largura)
|
||||
children: [new Paragraph({ children: [new TextRun("Celula")] })]
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
**Calculo de largura da tabela:**
|
||||
|
||||
Usar sempre `WidthType.DXA` — `WidthType.PERCENTAGE` quebra no Google Docs.
|
||||
|
||||
```javascript
|
||||
// Largura da tabela = soma de columnWidths = largura do conteudo
|
||||
// A4 com margens de 1": 11906 - 2880 = 9026 DXA
|
||||
width: { size: 9026, type: WidthType.DXA },
|
||||
columnWidths: [7000, 2026] // Deve somar a largura da tabela
|
||||
```
|
||||
|
||||
**Regras de largura:**
|
||||
- **Usar sempre `WidthType.DXA`** — nunca `WidthType.PERCENTAGE` (incompativel com Google Docs)
|
||||
- Largura da tabela deve igualar a soma de `columnWidths`
|
||||
- `width` da celula deve corresponder ao respectivo `columnWidth`
|
||||
- `margins` da celula sao padding interno - reduzem a area de conteudo, nao adicionam a largura
|
||||
- Para tabelas full-width: usar largura de conteudo (largura pagina menos margens esquerda e direita)
|
||||
|
||||
### Imagens
|
||||
|
||||
```javascript
|
||||
// CRITICO: parametro type e OBRIGATORIO
|
||||
new Paragraph({
|
||||
children: [new ImageRun({
|
||||
type: "png", // Obrigatorio: png, jpg, jpeg, gif, bmp, svg
|
||||
data: fs.readFileSync("image.png"),
|
||||
transformation: { width: 200, height: 150 },
|
||||
altText: { title: "Titulo", description: "Desc", name: "Nome" } // Os tres sao obrigatorios
|
||||
})]
|
||||
})
|
||||
```
|
||||
|
||||
### Quebras de pagina
|
||||
|
||||
```javascript
|
||||
// CRITICO: PageBreak deve estar dentro de um Paragraph
|
||||
new Paragraph({ children: [new PageBreak()] })
|
||||
|
||||
// Ou usar pageBreakBefore
|
||||
new Paragraph({ pageBreakBefore: true, children: [new TextRun("Nova pagina")] })
|
||||
```
|
||||
|
||||
### Indice (Table of Contents)
|
||||
|
||||
```javascript
|
||||
// CRITICO: Headings devem usar HeadingLevel APENAS - sem estilos custom
|
||||
new TableOfContents("Indice", { hyperlink: true, headingStyleRange: "1-3" })
|
||||
```
|
||||
|
||||
### Cabecalhos/Rodapes
|
||||
|
||||
```javascript
|
||||
sections: [{
|
||||
properties: {
|
||||
page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } // 1440 = 1 polegada
|
||||
},
|
||||
headers: {
|
||||
default: new Header({ children: [new Paragraph({ children: [new TextRun("Cabecalho")] })] })
|
||||
},
|
||||
footers: {
|
||||
default: new Footer({ children: [new Paragraph({
|
||||
children: [new TextRun("Pagina "), new TextRun({ children: [PageNumber.CURRENT] })]
|
||||
})] })
|
||||
},
|
||||
children: [/* conteudo */]
|
||||
}]
|
||||
```
|
||||
|
||||
### Regras criticas para docx-js
|
||||
|
||||
- **Definir tamanho de pagina explicitamente** - docx-js assume A4; para documentos PT/EU, A4 (11906 x 16838 DXA) e o padrao correcto
|
||||
- **Paisagem: passar dimensoes retrato** - docx-js troca largura/altura internamente; passar lado curto como `width`, lado longo como `height`, e definir `orientation: PageOrientation.LANDSCAPE`
|
||||
- **Nunca usar `\n`** - usar elementos Paragraph separados
|
||||
- **Nunca usar bullets unicode** - usar `LevelFormat.BULLET` com config numbering
|
||||
- **PageBreak deve estar em Paragraph** - standalone cria XML invalido
|
||||
- **ImageRun requer `type`** - especificar sempre png/jpg/etc
|
||||
- **Definir sempre `width` da tabela com DXA** - nunca usar `WidthType.PERCENTAGE` (quebra no Google Docs)
|
||||
- **Tabelas precisam de larguras duplas** - array `columnWidths` E `width` da celula, ambos devem corresponder
|
||||
- **Largura tabela = soma de columnWidths** - para DXA, garantir que somam exactamente
|
||||
- **Adicionar sempre margins nas celulas** - usar `margins: { top: 80, bottom: 80, left: 120, right: 120 }` para padding legivel
|
||||
- **Usar `ShadingType.CLEAR`** - nunca SOLID para shading de tabelas
|
||||
- **TOC requer HeadingLevel apenas** - sem estilos custom nos paragrafos de heading
|
||||
- **Override built-in styles** - usar IDs exactos: "Heading1", "Heading2", etc.
|
||||
- **Incluir `outlineLevel`** - necessario para TOC (0 para H1, 1 para H2, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Editar documentos existentes
|
||||
|
||||
**Seguir os 3 passos por ordem.**
|
||||
|
||||
### Passo 1: Descompactar
|
||||
```bash
|
||||
python scripts/office/unpack.py document.docx unpacked/
|
||||
```
|
||||
Extrai XML, pretty-prints, funde runs adjacentes e converte smart quotes para entidades XML (`“` etc.) para sobreviverem a edicao. Usar `--merge-runs false` para saltar a fusao de runs.
|
||||
|
||||
### Passo 2: Editar XML
|
||||
|
||||
Editar ficheiros em `unpacked/word/`. Ver Referencia XML abaixo para padroes.
|
||||
|
||||
**Usar "Claude" como autor** para tracked changes e comentarios, salvo se o utilizador pedir outro nome.
|
||||
|
||||
**Usar a ferramenta Edit directamente para substituicao de strings. Nao escrever scripts Python.** Scripts introduzem complexidade desnecessaria. A ferramenta Edit mostra exactamente o que esta a ser substituido.
|
||||
|
||||
**CRITICO: Usar smart quotes para novo conteudo.** Ao adicionar texto com apostrofos ou aspas, usar entidades XML para produzir smart quotes:
|
||||
```xml
|
||||
<!-- Usar estas entidades para tipografia profissional -->
|
||||
<w:t>Here’s a quote: “Hello”</w:t>
|
||||
```
|
||||
| Entidade | Caractere |
|
||||
|----------|-----------|
|
||||
| `‘` | ' (aspas simples esquerda) |
|
||||
| `’` | ' (aspas simples direita / apostrofo) |
|
||||
| `“` | " (aspas duplas esquerda) |
|
||||
| `”` | " (aspas duplas direita) |
|
||||
|
||||
**Adicionar comentarios:** Usar `comment.py` para tratar boilerplate em multiplos ficheiros XML (texto deve ser XML pre-escaped):
|
||||
```bash
|
||||
python scripts/comment.py unpacked/ 0 "Texto do comentario com & e ’"
|
||||
python scripts/comment.py unpacked/ 1 "Texto de resposta" --parent 0 # resposta ao comentario 0
|
||||
python scripts/comment.py unpacked/ 0 "Texto" --author "Autor Custom" # nome de autor custom
|
||||
```
|
||||
Depois adicionar marcadores ao document.xml (ver Comentarios na Referencia XML).
|
||||
|
||||
### Passo 3: Recompactar
|
||||
```bash
|
||||
python scripts/office/pack.py unpacked/ output.docx --original document.docx
|
||||
```
|
||||
Valida com auto-reparacao, condensa XML e cria DOCX. Usar `--validate false` para saltar.
|
||||
|
||||
**Auto-reparacao corrige:**
|
||||
- `durableId` >= 0x7FFFFFFF (regenera ID valido)
|
||||
- `xml:space="preserve"` em falta em `<w:t>` com whitespace
|
||||
|
||||
**Auto-reparacao nao corrige:**
|
||||
- XML malformado, nesting de elementos invalido, relacoes em falta, violacoes de schema
|
||||
|
||||
### Erros comuns
|
||||
|
||||
- **Substituir elementos `<w:r>` inteiros**: Ao adicionar tracked changes, substituir o bloco `<w:r>...</w:r>` completo com `<w:del>...<w:ins>...` como siblings. Nao injectar tags de tracked change dentro de um run.
|
||||
- **Preservar formatacao `<w:rPr>`**: Copiar o bloco `<w:rPr>` do run original para os runs de tracked change para manter bold, tamanho de fonte, etc.
|
||||
|
||||
---
|
||||
|
||||
## Referencia XML
|
||||
|
||||
### Conformidade com schema
|
||||
|
||||
- **Ordem de elementos em `<w:pPr>`**: `<w:pStyle>`, `<w:numPr>`, `<w:spacing>`, `<w:ind>`, `<w:jc>`, `<w:rPr>` por ultimo
|
||||
- **Whitespace**: Adicionar `xml:space="preserve"` a `<w:t>` com espacos no inicio/fim
|
||||
- **RSIDs**: Devem ser hex de 8 digitos (ex: `00AB1234`)
|
||||
|
||||
### Tracked Changes
|
||||
|
||||
**Insercao:**
|
||||
```xml
|
||||
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:t>texto inserido</w:t></w:r>
|
||||
</w:ins>
|
||||
```
|
||||
|
||||
**Eliminacao:**
|
||||
```xml
|
||||
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>texto eliminado</w:delText></w:r>
|
||||
</w:del>
|
||||
```
|
||||
|
||||
**Dentro de `<w:del>`**: Usar `<w:delText>` em vez de `<w:t>`, e `<w:delInstrText>` em vez de `<w:instrText>`.
|
||||
|
||||
**Edicoes minimas** - marcar apenas o que muda:
|
||||
```xml
|
||||
<!-- Alterar "30 dias" para "60 dias" -->
|
||||
<w:r><w:t>O prazo e de </w:t></w:r>
|
||||
<w:del w:id="1" w:author="Claude" w:date="...">
|
||||
<w:r><w:delText>30</w:delText></w:r>
|
||||
</w:del>
|
||||
<w:ins w:id="2" w:author="Claude" w:date="...">
|
||||
<w:r><w:t>60</w:t></w:r>
|
||||
</w:ins>
|
||||
<w:r><w:t> dias.</w:t></w:r>
|
||||
```
|
||||
|
||||
**Eliminar paragrafos/itens de lista inteiros** - ao remover TODO o conteudo de um paragrafo, marcar tambem o paragraph mark como eliminado para fundir com o proximo paragrafo. Adicionar `<w:del/>` dentro de `<w:pPr><w:rPr>`:
|
||||
```xml
|
||||
<w:p>
|
||||
<w:pPr>
|
||||
<w:numPr>...</w:numPr> <!-- numeracao de lista se presente -->
|
||||
<w:rPr>
|
||||
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z"/>
|
||||
</w:rPr>
|
||||
</w:pPr>
|
||||
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>Conteudo inteiro do paragrafo a ser eliminado...</w:delText></w:r>
|
||||
</w:del>
|
||||
</w:p>
|
||||
```
|
||||
Sem o `<w:del/>` em `<w:pPr><w:rPr>`, aceitar alteracoes deixa um paragrafo/item de lista vazio.
|
||||
|
||||
**Rejeitar insercao de outro autor** - aninhar eliminacao dentro da insercao:
|
||||
```xml
|
||||
<w:ins w:author="Maria" w:id="5">
|
||||
<w:del w:author="Claude" w:id="10">
|
||||
<w:r><w:delText>texto inserido por ela</w:delText></w:r>
|
||||
</w:del>
|
||||
</w:ins>
|
||||
```
|
||||
|
||||
**Restaurar eliminacao de outro autor** - adicionar insercao depois (nao modificar a eliminacao):
|
||||
```xml
|
||||
<w:del w:author="Maria" w:id="5">
|
||||
<w:r><w:delText>texto eliminado</w:delText></w:r>
|
||||
</w:del>
|
||||
<w:ins w:author="Claude" w:id="10">
|
||||
<w:r><w:t>texto eliminado</w:t></w:r>
|
||||
</w:ins>
|
||||
```
|
||||
|
||||
### Comentarios
|
||||
|
||||
Apos executar `comment.py` (ver Passo 2), adicionar marcadores ao document.xml. Para respostas, usar flag `--parent` e aninhar marcadores dentro dos do pai.
|
||||
|
||||
**CRITICO: `<w:commentRangeStart>` e `<w:commentRangeEnd>` sao siblings de `<w:r>`, nunca dentro de `<w:r>`.**
|
||||
|
||||
```xml
|
||||
<!-- Marcadores de comentario sao filhos directos de w:p, nunca dentro de w:r -->
|
||||
<w:commentRangeStart w:id="0"/>
|
||||
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>eliminado</w:delText></w:r>
|
||||
</w:del>
|
||||
<w:r><w:t> mais texto</w:t></w:r>
|
||||
<w:commentRangeEnd w:id="0"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
||||
|
||||
<!-- Comentario 0 com resposta 1 aninhada dentro -->
|
||||
<w:commentRangeStart w:id="0"/>
|
||||
<w:commentRangeStart w:id="1"/>
|
||||
<w:r><w:t>texto</w:t></w:r>
|
||||
<w:commentRangeEnd w:id="1"/>
|
||||
<w:commentRangeEnd w:id="0"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="1"/></w:r>
|
||||
```
|
||||
|
||||
### Imagens
|
||||
|
||||
1. Adicionar ficheiro de imagem a `word/media/`
|
||||
2. Adicionar relacao a `word/_rels/document.xml.rels`:
|
||||
```xml
|
||||
<Relationship Id="rId5" Type=".../image" Target="media/image1.png"/>
|
||||
```
|
||||
3. Adicionar content type a `[Content_Types].xml`:
|
||||
```xml
|
||||
<Default Extension="png" ContentType="image/png"/>
|
||||
```
|
||||
4. Referenciar no document.xml:
|
||||
```xml
|
||||
<w:drawing>
|
||||
<wp:inline>
|
||||
<wp:extent cx="914400" cy="914400"/> <!-- EMUs: 914400 = 1 polegada -->
|
||||
<a:graphic>
|
||||
<a:graphicData uri=".../picture">
|
||||
<pic:pic>
|
||||
<pic:blipFill><a:blip r:embed="rId5"/></pic:blipFill>
|
||||
</pic:pic>
|
||||
</a:graphicData>
|
||||
</a:graphic>
|
||||
</wp:inline>
|
||||
</w:drawing>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencias
|
||||
|
||||
- **pandoc**: Extracao de texto
|
||||
- **docx**: `npm install -g docx` (novos documentos)
|
||||
- **LibreOffice**: Conversao PDF (auto-configurado para ambientes sandbox via `scripts/office/soffice.py`)
|
||||
- **Poppler**: `pdftoppm` para imagens
|
||||
|
||||
---
|
||||
|
||||
## Integracao Descomplicar
|
||||
|
||||
### MCPs disponiveis
|
||||
|
||||
| MCP | Uso |
|
||||
|-----|-----|
|
||||
| `mcp__filesystem__*` | Ler/escrever ficheiros .docx locais, listar directorios |
|
||||
| `mcp__google-workspace__*` | Upload para Google Drive, conversao para Google Docs |
|
||||
| `mcp__ssh-unified__*` | Operacoes em ficheiros .docx em servidores remotos |
|
||||
|
||||
### Workflow tipico
|
||||
|
||||
1. **Criar documento** com docx-js conforme instrucoes acima
|
||||
2. **Validar** com `scripts/office/validate.py`
|
||||
3. **Guardar** via `mcp__filesystem__write_file` ou directamente no path do projecto
|
||||
4. **Upload** (opcional) via `mcp__google-workspace__drive_upload_file` para partilha com cliente
|
||||
|
||||
### Convencoes Descomplicar
|
||||
|
||||
- **Formato de data** em documentos: DD-MM-YYYY (ex: 06-03-2026)
|
||||
- **Formato monetario**: 1.234,56 EUR (separador milhar ponto, decimal virgula)
|
||||
- **Fonte padrao**: Arial 12pt
|
||||
- **Tamanho pagina padrao**: A4 (11906 x 16838 DXA)
|
||||
- **Autor para tracked changes**: "Claude" (salvo indicacao contraria)
|
||||
- **Idioma do documento**: PT-PT salvo indicacao contraria
|
||||
|
||||
---
|
||||
**Versao**: 1.0.0 | **Autor**: Descomplicar®
|
||||
Reference in New Issue
Block a user