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
| Formato | Método de conversão | Descrição |
|---|---|---|
.md | pandoc | Suporta YAML front-matter, tabelas GFM, listas, blocos de código, imagens |
.docx | pandoc | Estilos de título → títulos de capítulo; tabelas → tabelas estilizadas; imagens extraídas automaticamente |
.txt | Análise interna | Parágrafos por linhas em branco; linhas curtas numeradas (一、/ 1. / Capítulo X) → títulos de capítulo |
.html | Análise interna | Extrai <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
---
badgesseparados por;, prefixo!define fundo preto com texto branco.- Se
datenã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
| Comportamento | Regra |
|---|---|
| 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ário | Gerado 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 |
| Tabelas | Colunas ≥ 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 fonte | Açã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"> + ECharts | Capturado 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:
| Arquivo | Peso |
|---|---|
SourceHanSansCN-Regular.subset.ttf | 400 |
SourceHanSansCN-Bold.subset.ttf | 700 |
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):
- 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 - Remover
fonts/:make.pynã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). - Apenas alterar CSS: mude o primeiro nome de fonte em
--sansno início detemplates/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:
| Entrada | Saí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
| Entrada | Tamanho | Páginas | Tempo |
|---|---|---|---|
| md | 29 KB | 15 | ~6s |
| html | 105 KB + 2 gráficos ECharts | 21 | ~15s |
| docx | Estilos de título + tabelas | 2 | ~6s |
txt (samples/) | 1,2 KB | 2 | ~5s |
| md documento longo (regressão) | 71 KB | 21 | ~24s |
Dependências de ambiente
| Dependência | Estado atual | Se ausente |
|---|---|---|
| pandoc (≥2.19) | Execute pandoc -v para confirmar | md/docx não convertem |
| playwright + chromium | Ou Chrome / Edge do sistema | Incapaz de renderizar PDF |
| python-docx (opcional) | Apenas auxilia na análise | Nã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
.kvsã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.