Em poucas palavras
Uma leitura escolar sobre a história da imprensa. Os termos-chave são destacados em verde, as datas em âmbar e as pessoas e lugares em azul, e uma legenda na primeira página diz o que cada cor significa.
O que você vai compor
A leitura 2 de uma unidade de um livro escolar de história, Readings in Early Modern History: quatro páginas sobre como a imprensa se espalhou pela Europa a partir de Mainz entre 1450 e 1550, em uma página de 170 × 240 mm. Os editores marcaram o texto como faria um bom aluno, com um código que não muda no livro inteiro: os termos-chave sobre uma faixa verde, as datas sobre âmbar, as pessoas e os lugares sobre azul-claro. Uma legenda sob o título explica o código com as próprias três cores, e o glossário da última página abre cada verbete com o seu termo verde. As marcas são faixas sob texto comum, então as linhas quebram, hifenizam e justificam como se as faixas não existissem.
Esta receita responde a
- Como destaco as palavras-chave de um texto de estudo com cores que signifiquem algo cada uma (termos, datas, nomes)?
A resposta curta
// :mark[Mainz]{style="name"} in the text picks a style by id. The band is painted under
// words that stay ordinary text, so the lines break, hyphenate and justify as if the
// mark were not there, and a mark that runs over a line end gets a band on each line.
const band = (id, name) => ({
id, name,
background: col(id), // pale enough for ink at full contrast on top
color: col('ink'), // the words keep the colour of the text
// borderRadius: 0 is the default (square ends, as a highlighter pen leaves them)
paddingX: em(0.12), // the band reaches a little past the first and the last letter
paddingTop: em(0.04), paddingBottom: em(0.1), // and down past the descenders
});
const markStyles = [
band('term', t({ en: 'Key term', es: 'Término clave' })),
band('date', t({ en: 'Date', es: 'Fecha' })),
band('name', t({ en: 'Name', es: 'Nombre' })),
];
Ingredientes
- Funcionalidades
- DestaquesBoxesPaleta de cores semânticaAberturas desenhadasImagens nos designs de páginaAtributos de títuloCabeços e fóliosCabeços por tipo de páginaMargens espelhadasEstilos de parágrafoViúvas, órfãs e linhas curtas
- Também usa
- Bibliografias e glossáriosFigura e Tabela no seu idiomaTipos de recurso personalizadosFiguras e tabelas como recursos
- Tipografia
- Source Serif 4, Source Sans 3 (SIL OFL 1.1)
- Materiais
press-1400.jpg- The printing workshop on the opening page, a painting (Generated With Diffusion Models, original)
Preparo
#1 · Um estilo para cada tipo de palavra
O código está na resposta curta acima. markStyles declara três estilos com nome, e o texto escolhe um em cada marca: :mark[Johann Fust]{style="name"}, :mark[1455]{style="date"}, :mark[colophon]{style="term"} (destaques). Cada estilo diz o que significa (name é o que vê quem edita), então o Markdown guarda por que uma palavra foi marcada, não de que cor ela é. Mude a cor de um estilo e todas as datas do livro mudam junto. As pontas são retas, como por padrão desde o postext 1.52 (estilos de destaque): um marca-texto deixa pontas retas, e uma faixa arredondada se lê como um chip.
#2 · Três tons da paleta
const palette = {
ink: '#1f1c19', // text: a warm near-black
accent: '#8a3220', // kickers, rules, numbers: an iron-gall red
tint: '#f5f0e7', // the key's background
rule: '#d3cabc', // hairlines
muted: '#6b645b', // running heads, colophon
paper: '#ffffff',
term: '#cce8c8', // key terms: a pale green
date: '#fbe0a1', // dates: amber
name: '#cfe0f4', // people and places: a pale blue
};
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = [
...Object.entries(palette).map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })),
{ id: 'main-color', name: 'accent (defaults)', value: { hex: palette.accent, model: 'hex' } },
];
As três faixas são entradas da paleta, como a tinta e o acento, então quem abrir o livro no Sandbox pode trocar o código a partir de uma só amostra de cor. São claras, de luminosidade próxima à do fundo do quadro, e o texto sobre elas mantém um contraste de 12,6:1 ou mais; as três continuam distintas quando se encontram em uma linha, como em “In 1517 Martin Luther” na página 3. Uma marca não ocupa espaço: paddingX avança 0,12 em no espaço ao lado da frase e paddingBottom desce a faixa abaixo das descendentes, ambos pintados em um espaço que já existia.
#3 · A abertura: uma pintura sobre o título
const opener = {
enabled: true,
minHeight: mm(122), // the floor of the opener: the key starts on the same line
marginBottom: pt(0),
slot: {
elements: [
{ kind: 'image', id: 'press', resourceId: 'press', fit: 'cover',
placement: { anchor: { to: 'page', edge: 'top-left' },
size: { width: mm(170), height: mm(96) } } },
{ kind: 'text', id: 'kicker', content: '{attr.kicker}', fontFamily: SANS,
fontSize: pt(8.5), fontWeight: 700, letterSpacing: pt(1.6),
textTransform: 'uppercase', color: col('accent'), align: 'left',
placement: { anchor: { to: 'container', edge: 'top-left' },
offset: { x: mm(0), y: mm(82) } } },
{ kind: 'text', id: 'title', content: '{titleText}', fontFamily: SERIF,
fontSize: pt(26), lineHeight: 1.08, fontWeight: 700, color: col('ink'), align: 'left',
placement: { anchor: { to: '#kicker', edge: 'below' }, offset: { x: mm(0), y: mm(2) },
size: { width: mm(126), height: 'auto' } } },
{ kind: 'text', id: 'standfirst', content: '{attr.standfirst}', fontFamily: SERIF,
italic: true, fontSize: pt(10.5), lineHeight: LEAD / 10.5, color: col('ink'),
align: 'left',
placement: { anchor: { to: '#title', edge: 'below' }, offset: { x: mm(0), y: mm(3) },
size: { width: mm(118), height: 'auto' } } },
],
},
};
O título de primeiro nível imprime um design. A pintura é ancorada à página, então sangra no alto e nos dois lados, 170 por 96 mm, com fit: 'cover'. O chapéu e a linha-fina vêm de atributos da linha do título (atributos de título), e a legenda segue como um :::callout comum cujos itens de lista começam pelas três marcas. minHeight fixa a profundidade: a legenda começa na mesma linha, seja qual for o tamanho do título.
#4 · Cabeços conforme a paridade
const head = (id, content, parity, edge, x, extra = {}) => ({
kind: 'text', id, content, parity, pages: 'body',
fontFamily: SANS, fontSize: pt(7.5), fontWeight: 600, letterSpacing: pt(1.2),
textTransform: 'uppercase', color: col('muted'),
placement: { anchor: { to: 'page', edge }, offset: { x: mm(x), y: mm(13) } },
...extra,
});
const folio = { fontWeight: 700, color: col('ink') };
const header = {
elements: [
head('verso-folio', '{pageNumber}', 'even', 'top-left', OUTER, folio),
head('verso-title', '{title}', 'even', 'top-left', OUTER + 9),
head('recto-title', '{chapterTitle}', 'odd', 'top-right', -(OUTER + 9)),
head('recto-folio', '{pageNumber}', 'odd', 'top-right', -OUTER, folio),
],
};
const footer = {
elements: [head('drop-folio', '{pageNumber}', 'all', 'top', 0, {
...folio, pages: 'opener',
placement: { anchor: { to: 'container', edge: 'top' }, offset: { x: mm(0), y: mm(9) } },
})],
};
A página par leva o título da coleção e a ímpar o da leitura, ambos filtrados por parity e mantidos fora da abertura por pages: 'body' (elementos de texto). A abertura leva o fólio ao pé.
A receita completa
// ═══ Postext Cookbook · Nº 180 · Colour-coded highlights in a study reader ════════
// https://postext.dev/en/cookbook/colour-coded-study-highlights
// Code: MIT · Text: original (CC BY 4.0) · Picture: painting made for the recipe
// Fonts: Source Serif 4, Source Sans 3 (SIL OFL 1.1) · Needs postext ≥ 1.65.0
import {
buildDocumentWithFonts, renderPageToCanvas, registerResourceImage, defaultResourceTypes,
} from 'https://esm.sh/postext';
const LANG = 'en'; // @lang: the language of the sample document ('en' | 'es')
const RECIPE = 'colour-coded-study-highlights';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: semantic colours, three of them for the highlighter
const palette = {
ink: '#1f1c19', // text: a warm near-black
accent: '#8a3220', // kickers, rules, numbers: an iron-gall red
tint: '#f5f0e7', // the key's background
rule: '#d3cabc', // hairlines
muted: '#6b645b', // running heads, colophon
paper: '#ffffff',
term: '#cce8c8', // key terms: a pale green
date: '#fbe0a1', // dates: amber
name: '#cfe0f4', // people and places: a pale blue
};
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = [
...Object.entries(palette).map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } })),
{ id: 'main-color', name: 'accent (defaults)', value: { hex: palette.accent, model: 'hex' } },
];
// #endregion
const OUTER = 20; // outer margin in mm: the running heads align to it
const LEAD = 14.5; // body leading in pt
const SANS = 'Source Sans 3';
const SERIF = 'Source Serif 4';
// #region answer: three highlight styles, one per kind of word, linked to the palette
// :mark[Mainz]{style="name"} in the text picks a style by id. The band is painted under
// words that stay ordinary text, so the lines break, hyphenate and justify as if the
// mark were not there, and a mark that runs over a line end gets a band on each line.
const band = (id, name) => ({
id, name,
background: col(id), // pale enough for ink at full contrast on top
color: col('ink'), // the words keep the colour of the text
// borderRadius: 0 is the default (square ends, as a highlighter pen leaves them)
paddingX: em(0.12), // the band reaches a little past the first and the last letter
paddingTop: em(0.04), paddingBottom: em(0.1), // and down past the descenders
});
const markStyles = [
O script.js montado funciona como está: cole-o como script de módulo em qualquer página ou abra a receita no CodePen. Pasta da receita no GitHub ↗ (abre em uma nova aba)
Variações
#Arredonde as pontas das faixas
Um raio de um quinto do corpo dá as pontas suaves de uma caneta hidrográfica.
- // borderRadius: 0 is the default (square ends, as a highlighter pen leaves them)
+ borderRadius: em(0.2), // soft ends, as a felt-tip pen leaves them#Dê a cada linha a sua faixa
Com decorationBreak: 'clone', uma marca que passa de linha recebe a margem nas duas pontas de cada pedaço, como na página 3, onde “pamphlets” quebra depois de “pam-”.
paddingX: em(0.12), // the band reaches a little past the first and the last letter
+ decorationBreak: 'clone', // each line piece gets a whole bandErros comuns
- A cor sozinha não sobrevive a uma fotocópia em preto e branco, que é como muitas leituras chegam à sala de aula. O glossário também põe os termos em negrito; se os seus leitores vão fotocopiar as páginas, dê a um dos três tipos um segundo sinal próprio.
- Um id de estilo que
markStylesnão declara assume o primeiro estilo, sem erro na página (o Sandbox o aponta). Use ids curtos e confira como você os escreve no texto.
Créditos
- Receita
- Ignacio Ferro
- Texto
- The reading, its key, the review questions and the colophon · Ignacio Ferro · CC BY 4.0
- Imagens
- The printing workshop on the opening page, a painting · Generated With Diffusion Models · original
- Fontes
- Source Serif 4 (SIL OFL 1.1) · Source Sans 3 (SIL OFL 1.1)
- Código
- MIT, como o Postext
Editar este texto ↗ (abre em uma nova aba)Pasta da receita no GitHub ↗ (abre em uma nova aba)


