Communitygithub.com

swiss-pdf

Converte arquivos md / docx / txt / html em PDF A4 com estilo tipográfico suíço internacional.

O que é swiss-pdf?

O swiss-pdf é uma skill de agente de IA que transforma arquivos Markdown, DOCX, TXT ou HTML em PDF A4 com o estilo tipográfico suíço internacional (Swiss Style). Ele gera documentos limpos, com fundo branco, texto preto, linhas divisórias finas, números de capítulo grandes e a cor de destaque vermelha (#E5484D). A skill é ideal para engenheiros e profissionais que precisam gerar relatórios, white papers ou documentação técnica com aparência profissional e consistente, sem depender de editores gráficos. Ela suporta os principais formatos de entrada, gera automaticamente sumário, cabeçalho, rodapé e numeração de páginas, e oferece sete tipos de blocos estilizados (note, quote, inverse, warn, stat, check, kv). O processo é totalmente automatizado: recebe um arquivo (por arrastar e soltar ou linha de comando) e produz o PDF final, com tratamento inteligente de tabelas, imagens, gráficos (ECharts) e fontes (Source Han Sans embutidas via base64, sem necessidade de instalação).

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/echoBai83/swiss-pdf/tree/HEAD

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que swiss-pdf faz?

Converta md / docx / txt / html em PDF A4 com estilo tipográfico suíço internacional. Fundo branco, texto preto, linhas divisórias finas, números de capítulo grandes, fonte monoespaçada para números, única cor vermelha #E5484D.

Os tokens de design vêm de um caderno encadernado no estilo do International Style (números grandes de capítulo, linhas divisórias finas, cor de destaque única), adaptado para fluxo único com paginação automática, portanto documentos de qualquer tamanho podem ser processados diretamente.

Como usar

Método 1: Arrastar e soltar (recomendado)

Arraste o arquivo para swiss-pdf.bat → um PDF com o mesmo nome será gerado no mesmo diretório, junto com uma cópia xxx.pdf-src.html (fonte HTML para verificação).

Método 2: Linha de comando

python make.py arquivo_entrada                    # Gera PDF
python make.py arquivo_entrada --html             # Somente HTML (salvo como xxx.html, pode ser impresso manualmente no navegador)
python make.py arquivo_entrada -o saida.pdf
python make.py a.md b.docx c.txt                  # Lote
python make.py arquivo_entrada --no-cover --no-toc
python make.py arquivo_entrada --title "Título" --kick "Nota de rodapé" --date 2026.11.09

Formatos suportados

FormatoMétodo de conversãoDescrição
.mdpandocSuporta YAML front-matter, tabelas GFM, listas, blocos de código, imagens
.docxpandocEstilos de título → títulos de capítulo; tabelas → tabelas estilizadas; imagens extraídas automaticamente
.txtAnálise internaParágrafos por linhas em branco; linhas curtas numeradas (一、/ 1. / Capítulo X) → títulos de capítulo
.htmlAnálise internaExtrai <body>, remove script/style; <title> como título do documento

Capa: YAML front-matter

Escreva no topo do md (outros formatos usam parâmetros como --title):

---
title: Livro Branco de Segurança no Ciclismo Urbano
subtitle: Observações e Recomendações com Base em Amostragem de Três Cidades
kick: Pesquisa de Gestão de Tráfego
en: Urban Cycling Safety White Paper
slug: seguranca-ciclismo
nature: Versão Pública
project: Programa de Estudo de Sistemas de Mobilidade Lenta
party_a: Nome do Cliente
party_b: Nome do Contratado
stage: Pesquisa → Redação → Finalização
source: 01_Observações 02_Entrevistas 03_Plano
date: 2026.11.10
version: v2.1
badges: Público; !Importante; Dados Suportados
---
  • badges separados por ;, prefixo ! define fundo preto com texto branco.
  • Se date não for preenchido, usa a data atual automaticamente.
  • Funciona mesmo sem front-matter; a capa mostrará apenas título + data + espaço para versão.

Corpo: Seis blocos estilizados

No markdown, use ::: para envolver (cada linha dentro do bloco = um item):

::: note
Observação complementar, lembrete de calibre. Fundo cinza.
:::

::: quote
Citação de conclusão chave, com barra vertical esquerda de 3pt.
:::

::: inverse
Bloco de fundo preto com texto branco, para a frase mais importante.
:::

::: warn
Aviso com borda vermelha, único local onde é permitido usar cor.
:::

::: stat
4.280 | Total de amostras observadas || 24 | Pontos de observação || 3 | Cidades cobertas
:::

::: check
Cruzamento de horário de pico matinal (necessário chegar antes das 7:30)
Trechos iluminados à noite (necessário luz de preenchimento)
:::

::: kv
Páginas | Plano A 20 páginas / Plano C 32 páginas
Recomendação | Plano C, mas precisa complementar dados da segunda cidade
:::

stat usa número | descrição para formar uma célula, || separa células. kv usa chave | valor.

Comportamento automático

ComportamentoRegra
Numeração de capítulos# Título nível 1 → número grande 00/01/02…; se o título já contiver numeração como "01 " ou "一、", mantém
SumárioGerado apenas quando total de capítulos + subcapítulos (## ou inferior) ≥ 5; caso contrário, a página é omitida; títulos de capítulo têm âncoras clicáveis no PDF
TabelasColunas ≥ 6 reduz automaticamente o tamanho da fonte (table.wide); células numéricas alinhadas à direita + fonte monoespaçada
Cabeçalho e rodapéPágina de capa sem numeração; cabeçalho com título corrente à esquerda, rodapé com "Página i / Total N" à direita
Impressão@page A4, margens 14/15/13mm; títulos não separados do texto; linhas de tabela não quebradas entre páginas

Processamento adicional da fonte HTML (complementos testados)

Quando a fonte é uma "página web com design próprio", esta skill realiza automaticamente essas normalizações para evitar numerações soltas ou títulos duplicados após a reformatação:

Estrutura da fonteAção
<div class="sec-head"><span class="sec-num">3</span><h2>Título</h2></div>Converte para o cabeçalho de seção .sec do template (número extraído do span, título do h2)
<h1>03 Título</h1> / <h1>Título</h1>Mesmo acima; sem numeração, incrementa automaticamente na ordem de aparecimento
Parágrafo isolado com número <p>0</p>Descartado (comum em designs que usam número de capítulo como decoração)
<header class="masthead"> / <nav>Descartado (capa já é separada; cabeçalho/título grande/sumário repetidos poluiriam o corpo)
Seções <section>Mantidas como contêineres; título ainda precisa de sec-head ou h1 para entrar no sumário
<div id="xxx" class="chart"> + EChartsCapturado como PNG via navegador headless e incorporado; espera networkidle + 2,5s antes da captura

Pré-requisito para captura de gráficos: ECharts via CDN requer conectividade de rede; em ambientes offline, incorpore o echarts.min.js inline na fonte.

Fontes e pontuação

Fontes: Source Han Sans integrado no repositório, inline via @font-face

A pasta fonts/ contém dois arquivos; make.py incorpora seus base64 no <style> ao gerar o HTML, registrando a família de fontes Swiss Sans SC:

ArquivoPeso
SourceHanSansCN-Regular.subset.ttf400
SourceHanSansCN-Bold.subset.ttf700

O subconjunto cobre cerca de 7100 caracteres (ASCII + pontuação chinesa/inglesa + todos os 6763 caracteres GB2312). Conjunto de caracteres em fonts/charset.txt. Benefício: em outra máquina sem Source Han Sans instalado, a saída é idêntica, sem necessidade de instalar fontes.

O usuário pode substituir ou baixar fontes (detalhes em fonts/README.md):

  1. Substituir arquivos (recomendado): renomeie seu TTF para os nomes acima e sobrescreva. Subconjunto primeiro, senão o HTML levará 10 MB:
    pyftsubset sua-fonte-Regular.ttf --text-file=fonts/charset.txt --output-file=fonts/SourceHanSansCN-Regular.subset.ttf
    
  2. Remover fonts/: make.py não detecta arquivos e pula @font-face, usando a pilha de fontes do sistema no CSS (Source Han Sans SC/CN → Noto Sans SC → Noto Sans CJK SC → Mengyuan Hei CN → PingFang SC → Segoe UI Symbol).
  3. Apenas alterar CSS: mude o primeiro nome de fonte em --sans no início de templates/swiss.css.

⚠️ Deve ser .ttf (contorno TrueType), não .otf (CFF). Chromium ao imprimir PDF rebaixa fontes Web CFF para instruções de glifo Type3 (cada glifo armazena um caminho de desenho), inflando o tamanho várias vezes. Mesmo documento de 4 páginas: OTF → 328 KB / 205 Type3; TTF → 79 KB / 1 Type3.

Microsoft YaHei no Chromium falta símbolos como · (U+00B7), → ↓ ≤ ≥, que viram quadrados; portanto foi removido da pilha principal.

Aspas: conversão forçada para aspas curvas nacionais

convert.normalize_quotes() no último passo da conversão trata uniformemente títulos, capa, cabeçalho, sumário, tabelas e blocos estilizados:

EntradaSaída
「」“”
『』‘’
Aspas retas em código " 'Markdown via pandoc +smart converte automaticamente; dentro de <code> / <pre> não altera

A implementação substitui apenas 4 pontos de código (U+300C/D/E/F → U+201C/D/8/9), sem tocar atributos de tags HTML nem CSS/JS.

Registros de execução verificados

EntradaTamanhoPáginasTempo
md29 KB15~6s
html105 KB + 2 gráficos ECharts21~15s
docxEstilos de título + tabelas2~6s
txt (samples/)1,2 KB2~5s
md documento longo (regressão)71 KB21~24s

Dependências de ambiente

DependênciaEstado atualSe ausente
pandoc (≥2.19)Execute pandoc -v para confirmarmd/docx não convertem
playwright + chromiumOu Chrome / Edge do sistemaIncapaz de renderizar PDF
python-docx (opcional)Apenas auxilia na análiseNão afeta o fluxo principal

Especificar navegador: set SWISS_PDF_CHROME=<caminho_do_chrome.exe>

Estrutura de arquivos

swiss-pdf/
├── SKILL.md              Este arquivo
├── swiss-pdf.bat         Entrada por arrastar e soltar
├── make.py               Fluxo principal: converter → montar → renderizar
├── convert.py            Conversão de formatos → fragmento HTML + sintaxe de blocos
├── templates/
│   └── swiss.css         Todos os estilos (tokens de design + regras de impressão)
└── samples/              Amostras de exemplo nos três formatos

Limitações (o que não faz)

  • Paginação manual de caderno encadernado (conteúdo cuidadosamente posicionado por página, design de página dupla) o template não consegue; ainda requer HTML manual. Esta skill é focada em "finalização rápida de documentos comuns".
  • Layout de imagens depende do tamanho original no documento; não faz corte ou sangria.
  • Número de página de impressão à direita no sumário não implementado (elementos na página não têm acesso ao número da página); títulos de capítulo são clicáveis, rodapé tem "Página i / Total N".
  • Blocos de tabela muito curtos podem ser empurrados inteiros para a próxima página (para evitar quebra de tabelas de chave-valor, blocos .kv são definidos como não-quebráveis entre páginas).
  • Estilos complexos do Word (caixas de texto, WordArt, listas numeradas multinível) são degradados na conversão pelo pandoc.

Habilidades Relacionadas