laiss-docs
Gera documentos PDF em A4 a partir de um ficheiro JSON, com um design fixo: tipografia, paleta, capa e grelha iguais em todos os documentos. O corpo é escrito em blocos JSON, nunca em LaTeX, e o motor compõe e verifica o PDF.
Instalação
pip install laiss-docs
O pacote não tem dependências Python, mas precisa de três coisas do sistema que
o pip não instala: LuaLaTeX, pdftotext e pdfinfo.
A primeira compilação verifica o que falta na máquina e mostra o plano antes de
mexer no sistema. Se houver terminal, instala o que falta (o sudo pede a
password). Num sítio sem terminal, como um pipeline de CI, não instala nada e
diz o que instalar. Para tratar disto antes do primeiro documento:
laiss-docs deps --dry-run # o que falta e que comandos seriam corridos
laiss-docs deps # instala, depois de perguntar
laiss-docs deps -y # instala sem perguntar (CI)
laiss-docs doctor # confirma o que está pronto
O deps reconhece Debian, Ubuntu, Arch, Fedora, openSUSE, Alpine, macOS e
NixOS. Em CI, a instalação automática só acontece com
LAISSDOCS_AUTO_INSTALL=1.
Requisitos de sistema
- Python 3.9 ou mais recente, para correr o programa.
- LuaLaTeX (TeX Live, MacTeX ou MiKTeX), para compor o PDF. Não é opcional
e não pode ser trocado por Tectonic, que usa outro motor: a razão está em
docs/porque-lualatex.md, no repositório. pdftotextepdfinfo(poppler), para verificar o PDF produzido.
O deps instala os três. Instala também, se os pedires, o Graphviz e o
mermaid-cli, que só são necessários para diagramas.
Início rápido
laiss-docs templates # 8 estruturas prontas
laiss-docs new relatorio --template relatorio-tecnico --title "Relatório Técnico"
laiss-docs build relatorio
laiss-docs preview relatorio
O new cria a pasta com o doc.json e o src/. O build compila e verifica:
a compilar /caminho/relatorio ...
✓ pages 4 paginas
✓ a4 A4
✓ text-layer sem glifos colados
✓ refs todas as referencias resolvidas
✓ toc 5 entradas conferidas
/caminho/relatorio/out/relatorio-tecnico.pdf
Um documento criado com --template nasce com a estrutura certa e vazia. Cada
secção traz um guidance, que diz o que escrever ali. Vê-lo com:
laiss-docs outline relatorio
1. Âmbito e método ambito-e-metodo 0 blocos
O que ficou dentro e o que ficou fora. Como se mediu, com que versões e em que
ambiente. Sem isto, nenhum número do resto do relatório é verificável.
O guidance é instrução para quem escreve e não aparece no PDF. Escreve o
conteúdo de cada secção no doc.json e compila de novo. Se alguma verificação
falhar, o comando sai com código 1, e é isso que o torna utilizável em CI.
Estilos e templates
Duas coisas que se combinam:
- Um template diz a forma: as secções, a ordem, o que cada uma deve dizer.
- Um estilo diz como é: o arranque (capa ou não), as cores, a tipografia.
O mesmo study sai como artigo arXiv (sem capa, título no topo da página 1) ou
como capa da Laiss Labs, só mudando o estilo.
laiss-docs themes # lista
laiss-docs themes --show academico # as cores e as fontes
Escolhe-se no doc.json:
{ "title": "Um estudo", "theme": "academico" }
Os cinco que vêm com o pacote:
| Estilo | Arranque | Para quê |
|---|---|---|
laiss |
capa | A identidade da casa: Inter, laranja no acento, barra e marca |
book |
capa | Livro genérico: serifada, capa sóbria sem cor de marca |
arxiv |
título no topo | Artigo científico: sem capa, resumo na página 1, Times a 10pt |
academico |
capa | Serifada com capa sóbria |
corporativo |
capa | Azul-marinho de marca, títulos em maiúsculas |
A coluna «arranque» é a diferença de fundo. capa é uma página de rosto
inteira, com barra, marca e caixa de autor, e o resumo numa página a seguir ao
índice. título no topo põe o título, os autores e o resumo no alto da página
1, e o texto começa logo a seguir: é o que distingue um artigo científico de um
livro, e não é uma questão de cor.
Sem theme, o documento sai com a identidade Laiss, exactamente como antes.
As cores são papéis, não valores
O motor nunca sabe que o acento é laranja: pergunta por accent. Um tema
académico define accent a preto e o documento inteiro acompanha, sem uma
linha de LaTeX mudar. Os nomes que se podem definir:
| Papel | O que pinta |
|---|---|
ink, ink3, ink4 |
Texto principal, secundário, terciário |
accent, accentstrong, accentsoft, accentline |
Destaque: números de secção, filetes |
deep, deepdeep, deepsoft, deepline |
Subtítulos e caixas de informação |
paper1, paper2, paper3 |
Fundos |
hairline, hairlinestrong |
Filetes |
greenok, redno |
Confirmação e risco |
Um nome desconhecido falha na leitura, com a lista dos que existem. Um typo numa cor não é ignorado: o documento sairia com o valor da casa e ninguém dava por isso.
Extrair e personalizar
Os templates e os estilos vêm dentro do pacote. Para os editar:
laiss-docs eject # copia templates/ e themes/ para a pasta actual
Ficam em ficheiros que se abrem num editor. O motor procura primeiro nesta
pasta e só depois no pacote, por isso o que mudares ganha, sem mais nenhum
passo. Põe-nos ao lado do doc.json e viajam com o projecto.
Um estilo novo é um ficheiro em themes/; um template novo é um ficheiro em
templates/. O motor descobre-os sozinho e valida-os antes de compor:
laiss-docs themes # um estilo inválido aparece marcado com !
A validação não é só de forma. Verifica que o layout existe, que o ficheiro de
layout está instalado, e que a fonte pedida existe no sistema ou na árvore do
TeX. Um estilo que não compõe é recusado no build, com o motivo, em vez de
falhar a meio do LaTeX com um erro que não aponta para o tema.
O teu tema
laiss-docs theme "Cliente XPTO" --from arxiv
Cria o JSON em ~/.local/share/laiss-docs/themes (ou numa pasta themes/ ao
lado do documento, que tem prioridade). Muda as cores e as fontes no ficheiro;
o resto do documento acompanha.
Para uma marca que precisa de uma fonte própria, põe os .otf numa pasta e
declara o prefixo e o caminho:
{
"fonts": {
"body": "MinhaMarca",
"body_file": "minhamarca",
"body_path": "/caminho/para/fontes/"
}
}
Uma fonte que exista na árvore do TeX não precisa de ser distribuída: o motor
encontra-a com o kpsewhich e usa-a. É assim que o tema académico usa a Tex
Gyre Termes, que já vem com qualquer instalação.
Mancha, cabeçalho e corpo
Além das cores, um estilo diz como a página é feita. São três blocos, todos opcionais: um estilo que os não traga fica com a mancha e o corpo da casa.
{
"page": { "width": "165mm", "height": "247mm", "top": "22mm" },
"text": { "size": "10pt", "parindent": "0pt", "parskip": "5.5pt",
"justify": "1" },
"chrome": { "header_center": "runningHead", "header_right": "A Preprint",
"undertitle": "A Preprint", "footer_center": "\u005cthepage" }
}
page é a mancha: a largura e a altura do texto, e a distância ao topo. O
headheight, o headsep e o footskip também se podem declarar, quando o
cabeçalho precisa de mais espaço do que o normal.
text é o corpo do texto. O size vai para a classe do documento, e não só
para o \fontsize: sem isso o LaTeX calculava o resumo, as listas e as
legendas a 11pt e o texto a 10pt, e a página saía com duas medidas. Um valor
que o article.cls não conheça (10pt, 11pt, 12pt) é recusado antes de
compor.
chrome é o cabeçalho e o rodapé. O header_center aceita runningHead, que
lê o título curto do documento: um estilo não sabe que documento o vai
usar, e um título cravado no JSON saía em todos os que o escolhessem.
O bloco heading já existia para a família dos títulos; ganhou o rule, que
liga e desliga o filete por baixo do título de secção. Um artigo científico
não o leva.
Um artigo não tem caixas
As caixas note, warn e rule são uma forma de página web: o fundo e a
barra lateral separam o conteúdo do texto como se fosse de outra natureza. Num
artigo científico o mesmo conteúdo é um parágrafo recuado com o título a
abrir, em negrito e itálico:
A reading to avoid. The rule curve has a step, and it is tempting to say the model understood at that moment.
O recuo estreita a medida e marca a mudança de voz; o título diz de que voz se trata. É assim que se escreve um Remark, um Limitations ou uma nota de método numa secção. O recuo é o mesmo do resumo (2,5em de cada lado), para o documento ter um só recuo de voz.
Isto é decidido pelo layout, não pelo bloco: o mesmo doc.json com theme: "arxiv" produz o parágrafo recuado, e com theme: "laiss" produz a caixa.
Não há nada a mudar no documento.
Pela mesma razão, um estilo de artigo não tem a sans da casa em lado nenhum.
Os rótulos pequenos, as notas de referência e as legendas de figura passam por
\laissSansFamily, que resolve para serifada. A referência (arxiv.sty) não
tem uma única fonte sem serifa, e o PDF de um paper também não deve ter.
Templates
Um template é a forma de um documento: a ordem das secções, o que cada uma deve dizer, e os metadados do género. Não tem texto, tem intenção.
laiss-docs templates # lista, por género
laiss-docs templates --show proposta-comercial # estrutura completa
Os onze que vêm com o pacote. As três primeiras são as formas longas, e vão do maior para o menor: um livro, um paper, um estudo.
| Template | Género | Para quê |
|---|---|---|
book |
livro | Um livro em partes e capítulos, para ler do princípio ao fim |
laiss-paper |
paper | Um paper técnico: contribuição, método, avaliação, resultados |
study |
paper | Forma de paper arXiv, em inglês: related work, method, experiments |
relatorio-tecnico |
tecnico | Estado de um sistema, com medições e recomendações |
nota-decisao |
tecnico | Uma decisão tomada, as alternativas, e o motivo |
manual-utilizador |
tecnico | Como se faz uma tarefa, passo a passo |
estudo-tecnico |
academico | Uma pergunta, a evidência, e uma resposta argumentada |
proposta-comercial |
negocio | O que se propõe a um cliente, por quanto, e em quanto tempo |
apresentacao-projecto |
negocio | O produto, o fluxo, e onde ganha dinheiro |
runbook-operacoes |
operacional | O que fazer quando algo falha, às três da manhã |
politica-interna |
juridico | Uma regra da organização, com âmbito e consequências |
Livro, paper ou estudo
Os três parecem próximos e não são. A diferença está no que o leitor faz com o documento:
booké lido de seguida, por alguém que quer aprender o assunto. Tem partes, capítulos numerados, prefácio sem número, colofão, e uma conclusão que também não numera. Se o leitor consulta em vez de ler, é um manual.laiss-paperé avaliado por um par. Tem uma secção de avaliação com linha de base, porque um número sem comparação não diz se é bom. A discussão diz o que os resultados não provam.studyé a forma do arXiv, em inglês: Related Work, Method, Experiments, Results, Discussion. É escrito para ser lido e citado fora da organização.
O study nasce em en-US mesmo que o teu sistema esteja em português. O
idioma do template ganha ao --lang por omissão; um --lang explícito ganha
ao do template.
Os teus templates
Põe ficheiros .json em ~/.local/share/laiss-docs/templates
(~/Library/Application Support/laiss-docs/templates no macOS). Também podes
pôr uma pasta templates/ ao lado do documento, e essa ganha às outras: serve
para um documento fixar a sua versão de um template.
Um template do utilizador com o mesmo id de um do pacote substitui-o. O
laiss-docs templates mostra [utilizador] ao lado, para se saber qual está a
ganhar.
laiss-docs template "Relatório de obra" --genre operacional # do zero
laiss-docs template "Da apresentação" --from-doc examples/habitera-apresentacao
O segundo copia a forma de um documento que já existe, com as secções e os
metadados, e deixa o guidance vazio para preencheres. A partir de um
documento bom, é o caminho mais rápido para repetir a estrutura.
Um template mal escrito não é ignorado em silêncio: aparece em
laiss-docs templates com o motivo, e os outros continuam a funcionar.
Os comandos
Todos aceitam --json, que imprime o resultado em JSON em vez de texto.
| Comando | O que faz | Exemplo |
|---|---|---|
doctor |
Diz o que falta nesta máquina: motor, poppler, fontes, pacotes LaTeX, idiomas. | laiss-docs doctor |
deps |
Instala as dependências de sistema com o gestor da distribuição. | laiss-docs deps --dry-run |
templates |
Lista as estruturas de documento disponíveis. | laiss-docs templates |
template |
Cria um template novo, do zero ou a partir de um documento. | laiss-docs template "Relatório" --from-doc doc/ |
new |
Cria um documento. Aceita --template, --title, --subtitle, --lang, --from-json, --brief. |
laiss-docs new relatorio --template relatorio-tecnico |
build |
Compila o documento e corre as cinco verificações. | laiss-docs build relatorio |
check |
Verifica o PDF que já existe, sem recompilar. | laiss-docs check relatorio |
preview |
Abre o PDF no leitor do sistema. | laiss-docs preview relatorio |
outline |
Lista as secções com o id e o número de blocos. |
laiss-docs outline relatorio |
add |
Acrescenta uma secção, com blocos vindos de um ficheiro JSON. | laiss-docs add relatorio "Anexo" --blocks b.json |
read |
Mostra o conteúdo de uma secção, bloco a bloco. | laiss-docs read relatorio introducao |
generate |
Pede texto a um modelo, para uma secção existente ou nova. | laiss-docs generate relatorio --section introducao --instruction "acrescenta um exemplo" |
ai |
Testa a ligação ao endpoint de IA, sem gerar documento. | laiss-docs ai |
schema |
Imprime o JSON Schema do doc.json. |
laiss-docs schema |
locales |
Lista os idiomas suportados. | laiss-docs locales |
init |
Instala ou actualiza as fontes e os estilos. | laiss-docs init |
mcp |
Arranca o servidor MCP em stdio, para agentes AI. | laiss-docs mcp |
Sem nome de documento, build, check, preview, outline, add, read e
generate usam o documento da pasta actual, ou a única pasta que ali tenha um
doc.json.
Como se escreve um documento
O doc.json tem os metadados e as secções. Cada secção tem um title e uma
lista de blocks. Este ficheiro compila e produz quatro páginas:
{
"title": "Relatório de Novembro",
"subtitle": "O que mudou no motor de compilação.",
"language": "pt-PT",
"sections": [
{
"title": "Estado actual",
"label": "PARTE 1",
"blocks": [
{"type": "p", "text": "O motor compila três vezes e verifica o PDF no fim. Um **parágrafo** aceita `código` e *ênfase*."},
{"type": "h", "level": 2, "text": "O que foi feito"},
{"type": "ul", "items": ["Blocos passaram a JSON", "Design fixo", "Cinco idiomas"]},
{"type": "note", "title": "Uma nota", "text": "As fontes vão dentro do pacote."},
{"type": "chart", "caption": "Tempo por passagem", "unit": " s", "labels": ["1ª", "2ª", "3ª"], "values": [3, 2, 2]}
]
}
]
}
Guarda-o e corre laiss-docs new relatorio --from-json modelo.json, seguido de
laiss-docs build relatorio. Os campos de topo mais usados são title
(obrigatório), subtitle, language, date (AAAA-MM-DD), classification,
coverFrom, coverTo, keywords, toc (índice, ligado por omissão) e
colophon (página final, desligada por omissão).
Os blocos disponíveis:
| Tipo | Campos | Para quê |
|---|---|---|
p |
text |
Um parágrafo. |
h |
text, level (2 ou 3) |
Subtítulo dentro de uma secção. |
ul, ol |
items (lista de textos) |
Lista com marcas ou numerada. |
dl |
items (term e def) |
Lista de definições. |
note, warn, rule |
text, title opcional |
Caixa azul (informação), laranja (risco), cinza (norma). Num estilo de artigo, um parágrafo recuado com o título a abrir. |
code, output |
text, label opcional |
Bloco verbatim: o que o leitor escreve, e o que ele vê. |
table |
columns, rows, caption e widths opcionais |
Tabela com cabeçalho repetido quando passa de página. |
quote |
text, source opcional |
Citação. |
pagebreak |
nenhum | Força página nova. |
mermaid, graphviz |
source, caption |
Diagrama desenhado a partir de código. |
chart |
labels, values, caption |
Gráfico de barras a partir de números. |
figure |
path, caption |
Imagem que já existe. |
refs |
items (text, url, note) |
Lista de referências. |
Dentro dos blocos de texto há quatro marcas: **forte**, *ênfase*,
`código` e [[caminho/ficheiro]]. Tudo o resto é texto literal, incluindo
_, % e #. Não escrevas comandos LaTeX: apareceriam no PDF como texto.
O caption das quatro famílias de figura é obrigatório. Um documento também
pode ter abstract (resumo, depois do índice e sem número) e appendices
(anexos numerados ANEXO A, B). A referência completa está em docs/blocos.md,
no repositório.
Figuras e diagramas
| Tipo | O que precisa de estar instalado |
|---|---|
chart |
Nada. É desenhado pelo próprio motor, com TikZ, a partir dos números. |
figure com PNG, JPEG ou PDF |
Nada. |
figure com SVG |
O rsvg-convert (pacote librsvg2-bin em Debian e Ubuntu). |
graphviz |
O dot, do pacote Graphviz. |
mermaid |
O @mermaid-js/mermaid-cli e um browser headless. |
Para saber o que está disponível nesta máquina antes de escrever o bloco, usa a
ferramenta laiss_diagrams do servidor MCP, ou simplesmente escolhe chart,
que funciona sempre.
Os caminhos das figuras são relativos à pasta do documento. Quando há figuras, o
índice de figuras é gerado automaticamente; "listOfFigures": false desliga-o.
Idiomas
laiss-docs locales
| Código | Idioma | Também aceita |
|---|---|---|
pt-PT |
Português (Portugal) | pt, portugues |
en-US |
English (US) | en, english |
es-ES |
Español (España) | es, spanish |
fr-FR |
Français (France) | fr, french |
de-DE |
Deutsch (Deutschland) | de, german |
O idioma muda a hifenização, a data por extenso, o título do índice, as etiquetas da capa e os títulos por omissão das caixas. Não muda o design: a tipografia e a paleta são as mesmas em todos os idiomas.
Uso por agentes AI
O laiss-docs mcp arranca um servidor MCP sobre stdio, sem dependências. No
Cursor, cria .cursor/mcp.json:
{
"mcpServers": {
"laiss-docs": {
"command": "laiss-docs",
"args": ["mcp"]
}
}
}
O servidor expõe 25 ferramentas: escolher um template, criar documento, ler e editar secções e blocos, gerir resumo e anexos, compilar e verificar.
Um agente começa por laiss_guide, que devolve o processo inteiro, os tipos de
bloco, a marcação permitida e os erros comuns. Sem ela, um agente tenta
escrever LaTeX e conclui que a ferramenta está avariada.
O passo seguinte, e o que faz a diferença, é a escolha da estrutura:
| Ferramenta | O que devolve |
|---|---|
laiss_templates |
Os templates que existem, por género, com descrição |
laiss_template |
A estrutura de um, com o guidance de cada secção |
laiss_create_from_template |
O documento criado já com essa estrutura |
O laiss_create_from_template devolve cada secção com a instrução do que
escrever ali, e é o caminho recomendado para começar: o agente recebe a forma
e a intenção de uma vez, em vez de inventar secções. A alternativa,
laiss_add_section, continua disponível para documentos fora de qualquer
molde.
O resto do ciclo é laiss_outline (que id existe), laiss_add_blocks e
laiss_build, que devolve as verificações e os erros no formato
ficheiro:linha: mensagem. O contrato completo está em docs/mcp.md, no
repositório.
Também podes gerar texto com um modelo, por endpoint compatível com a API de chat completions (OpenAI, Ollama, LM Studio, vLLM, llama.cpp):
export LAISSDOCS_BASE_URL="http://localhost:1234/v1"
export LAISSDOCS_MODEL="o-modelo-que-usas"
laiss-docs ai
laiss-docs generate relatorio --section introducao --instruction "acrescenta um exemplo"
Limites conhecidos
- Só A4 retrato. Outros formatos e orientação não estão previstos.
- O corpo são blocos JSON, não Markdown livre. A estrutura é escolhida num
campo
type; um ficheiro Markdown não se converte. - Sem índice remissivo nem bibliografia. Há lista de referências num anexo, formatada como texto, sem citações numeradas no corpo.
- O design não se edita num documento. Um aspecto diferente é um parâmetro
do
doc.json, ou não é possível.
Licença
MIT, Laiss Labs. As fontes mantêm as suas licenças: Inter e JetBrains Mono, OFL 1.1.
Metadata
Release files for laiss-docs 1.6.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| laiss_docs-1.6.1.tar.gz | 7.8 MB | Without provenance | Details for laiss_docs-1.6.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| laiss_docs-1.6.1-py3-none-any.whl | Python 3 | none | any | Details for laiss_docs-1.6.1-py3-none-any.whl |
Total release size: 13.1 MB
Release files / laiss_docs-1.6.1.tar.gz
| Download URL | laiss_docs-1.6.1.tar.gz |
|---|---|
| Size | 7.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
766f6db9b70374eac3a2fcb1fd0687ff0dc06fc01e935c6f6bb2eb8d82e1e4ec
|
|
BLAKE2b-256 checksum How to use checksums |
6e3921b72527a95eb7e9112426fa9543d3bbbe71e3b1a54816daff804593344b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / laiss_docs-1.6.1-py3-none-any.whl
| Download URL | laiss_docs-1.6.1-py3-none-any.whl |
|---|---|
| Size | 5.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8eab99af4e62219cdae209e54255a70f2bb051f5cde751b28b17d1c8d10ea1d6
|
|
BLAKE2b-256 checksum How to use checksums |
dd40676ebd1b58cc63784ed1fa57823609c01b3d65459b2f2cc4350d35ea8f4f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Security for laiss-docs 1.6.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.