En poques paraules
Una lectura escolar sobre la història de la impremta. Els termes clau van en verd, les dates en ambre i les persones i els llocs en blau, i una clau a la primera pàgina explica què vol dir cada color.
Què compondràs
La lectura 2 d'una unitat d'un llibre escolar d'història, Lecturas de historia moderna: quatre pàgines sobre com la impremta es va estendre per Europa des de Magúncia entre el 1450 i el 1550, en una pàgina de 170 × 240 mm. Els editors han marcat el text com ho faria un bon estudiant, amb un codi que no canvia en tot el llibre: els termes clau sobre una franja verda, les dates sobre ambre, les persones i els llocs sobre blau pàl·lid. Una clau sota el títol explica el codi amb els tres colors, i el glossari de l'última pàgina obre cada entrada amb el seu terme en verd. Les marques són franges sota text corrent, de manera que les línies es tallen, es divideixen i es justifiquen com si no hi fossin.
Aquesta recepta respon a
- Com ressalto les paraules clau d'un text d'estudi amb colors que vulguin dir alguna cosa cadascun (termes, dates, noms)?
La 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' })),
];
Ingredients
- Funcions
- Marques de ressaltatRequadresPaleta de color semànticaObertures dissenyadesImatges als dissenys de pàginaAtributs de títolCapçaleres i folisCapçaleres segons el tipus de pàginaMarges simètricsEstils de paràgrafVídues, òrfenes i línies curtes
- També fa servir
- Bibliografies i glossarisFigura i Taula en la teva llenguaTipus de recurs propisFigures i taules com a recursos
- Tipografia
- Source Serif 4, Source Sans 3 (SIL OFL 1.1)
- Recursos
press-1400.jpg- The printing workshop on the opening page, a painting (Generated With Diffusion Models, original)
Elaboració
#1 · Un estil per a cada mena de paraula
El codi és la resposta curta de més amunt. markStyles declara tres estils amb nom, i el text en tria un a cada marca: :mark[Johann Fust]{style="name"}, :mark[1455]{style="date"}, :mark[colofón]{style="term"} (marques de ressaltat). Cada estil diu què vol dir (name és el que veu qui edita), de manera que el Markdown guarda per què es marca una paraula i no de quin color va. Si canvies el color d'un estil, canvien amb ell totes les dates del llibre. Els extrems són rectes, com per defecte des de postext 1.52 (estils de ressaltat): un retolador fluorescent deixa els extrems rectes, i una franja arrodonida es llegeix com un xip.
#2 · Tres tintes de la 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' } },
];
Les tres franges són entrades de la paleta, igual que la tinta i l'accent, així que qui obri el llibre al Sandbox pot canviar el codi des d'una sola mostra de color. Són pàl·lides, d'una lluminositat semblant a la del fons del requadre, i el text a sobre conserva un contrast de 12,6:1 o més; les tres es distingeixen quan es troben en una línia, com a «En 1517, Martín Lutero» a la pàgina 3. Una marca no ocupa espai: paddingX entra 0,12 em a l'espai del costat de la frase i paddingBottom baixa la franja per sota dels traços descendents, i tots dos es pinten en un espai que ja hi era.
#3 · L'obertura: una pintura sobre el títol
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' } } },
],
},
};
El títol de primer nivell imprimeix un disseny. La pintura s'ancora a la pàgina, així que surt a sang per dalt i pels dos costats, 170 per 96 mm, amb fit: 'cover'. L'avanttítol i l'entradeta surten d'atributs de la línia del títol (atributs de títol), i la clau segueix com un :::callout corrent amb uns elements de llista que comencen per les tres marques. minHeight fixa la profunditat: la clau comença a la mateixa línia per molt que ocupi el títol.
#4 · Capçaleres segons la paritat
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) } },
})],
};
La pàgina parella porta el títol de la col·lecció i la senar el de la lectura, totes dues filtrades per parity i fora de l'obertura gràcies a pages: 'body' (elements de text). L'obertura porta el foli al peu.
La recepta 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 = 'es'; // @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 = [
L'script.js compost funciona tal com és: enganxa'l com a script de mòdul en qualsevol pàgina o obre la recepta a CodePen. Carpeta de la recepta a GitHub ↗ (s'obre en una pestanya nova)
Variants
#Arrodoneix els extrems de les franges
Un radi d'una cinquena part del cos dona els extrems suaus d'un retolador.
- // 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#Dona a cada línia la seva franja
Amb decorationBreak: 'clone', una marca que passa de línia porta el farciment als dos extrems de cada tros, en lloc de quedar recta on es talla la línia.
paddingX: em(0.12), // the band reaches a little past the first and the last letter
+ decorationBreak: 'clone', // each line piece gets a whole bandErrors freqüents
- El color sol no sobreviu a una fotocòpia en blanc i negre, que és com arriben moltes lectures a l'aula. El glossari posa a més els termes en negreta; si els teus lectors fotocopiaran les pàgines, dona a una de les tres menes un segon senyal propi.
- Un id d'estil que
markStylesno declara pren el primer estil, sense cap error a la pàgina (el Sandbox l'assenyala). Fes servir ids curts i revisa com els escrius al text.
Crèdits
- Recepta
- Ignacio Ferro
- Text
- The reading, its key, the review questions and the colophon · Ignacio Ferro · CC BY 4.0
- Imatges
- The printing workshop on the opening page, a painting · Generated With Diffusion Models · original
- Fonts
- Source Serif 4 (SIL OFL 1.1) · Source Sans 3 (SIL OFL 1.1)
- Codi
- MIT, com Postext
Editar aquest text ↗ (s'obre en una pestanya nova)Carpeta de la recepta a GitHub ↗ (s'obre en una pestanya nova)


