Saltar al contingut principal
Recepta número 176

Receptari · Capítol 2 · Text i tipografia

Xifres elzevirianes, de caixa alta i tabulars

Els comptes de Walden: figureStyle dona xifres de caixa alta als títols en versaletes i xifres tabulars als comptes; la prosa conserva les elzevirianes.

En aquesta pàgina
Sortida
Canvas · PDF
Nivell
Intermedi
Postext
Provada amb Postext 1.65.0
Requereix ≥ 1.65.0 · postext-pdf ≥ 1.65.0
Llicència
Actualitzada el 31 d’oct. del 2026
Codi MIT · Text CC BY 4.0
  • Mostra en castellà: encara no hi ha edició en català
  • Format 140 × 216 mm
  • 1 columna
  • Alegreya 10,8/14,5
  • Alegreya SC
  • Alegreya SC@lnum
  • Alegreya Sans
  • Alegreya@tnum
  • 6 pàgines
  • Nivell
  • Postext 1.65.0
  • Compost en 97 ms
  • 160 línies de codi

En poques paraules

Una edició breu dels comptes domèstics que Thoreau va publicar a Walden. Les xifres del text són petites com les minúscules, els anys dels títols fan l'alçada de les majúscules i les sumes dels comptes s'alineen en columna.

Què compondràs

Una edició breu dels comptes que Thoreau va publicar al primer capítol de Walden: el que li va costar la casa, el que li va donar el camp de mongetes, el que va menjar en vuit mesos. Va en una pàgina de 140 × 216 mm amb la família Alegreya, i l'obertura porta el gravat de 1854 de la cabana. Les xifres canvien segons la feina que fan. A la prosa, març de 1845 i $13,34 van en xifres elzevirianes, que pugen i baixen com les minúscules, i les dates no destaquen a la línia. Els títols van en versaletes, i els seus anys fan l'alçada de les majúscules. Als comptes totes les xifres tenen la mateixa amplada, de manera que els cèntims de tretze línies de taules, llistons i claus queden l'un sota l'altre fins al total.

Aquesta recepta respon a

  • Com componc xifres elzevirianes al text, xifres de caixa alta als títols i xifres tabulars a les taules?
  • Com componc il·lustracions sense numerar: ornaments, vinyetes, logotips?

La resposta curta

script.js · línies 34–55al codi complet
// Alegreya's own figures are old-style, so the prose asks for none: the cut Fontsource
// serves has no onum, and 'oldstyle' would change nothing (see the write-up).
const bodyText = {
  fontFamily: TEXT, fontSize: pt(10.8), lineHeight: pt(LEAD), color: col('ink'),
  boldColor: col('ink'), italicColor: col('ink'), referenceColor: col('ink'),
  textAlign: 'justify', firstLineIndent: mm(4.5), indentAfterHeading: false,
  hyphenation: { enabled: true }, optimalLineBreaking: true,
  avoidWidows: true, avoidOrphans: true, avoidRunts: true,
};
// Small capitals take lining figures (lnum), at the height of the capitals around them.
const section = { level: 2, fontFamily: CAPS, fontSize: pt(12.5), lineHeight: pt(LEAD),
  fontWeight: 400, letterSpacing: pt(0.6), color: col('accent'), figureStyle: 'lining',
  marginTop: pt(LEAD), marginBottom: pt(0) };
// The accounts: every figure on one width (tnum), so the cents stand in columns.
// 'tabular' keeps the font's form, old-style; 'lining-tabular' would set them at cap height.
const tableStyle = {
  figureStyle: 'tabular', bodyFontFamily: TEXT, bodyFontSize: pt(9.8), bodyColor: col('ink'),
  rules: 'booktabs', groupRules: true, borderColor: col('rule'), lightRuleWidth: pt(0.4),
  heavyRuleWidth: pt(0.7), headerBackgroundEnabled: false, headerFontFamily: TEXT,
  headerFontSize: pt(9.8), headerColor: col('ink'), headerBold: false, headerItalic: false,
  cellPadding: mm(0.7),
};

Ingredients

Tipografia
Alegreya, Alegreya SC, Alegreya Sans (SIL OFL 1.1)
Recursos
  • cabin-860.jpg
  • The vignette of Thoreau’s cabin from the title page of the first edition (1854), cropped and levelled to black on white (Ticknor and Fields, Boston, 1854 (engraver unknown), domini públic)

Elaboració

#1 · Un estil de xifres per estil de text

El codi d'aquest pas és la resposta curta, més amunt. figureStyle demana a la font d'un estil les seves xifres OpenType (estils de xifres). El cos no demana res, perquè les xifres pròpies d'Alegreya ja són elzevirianes i proporcionals: l'1 fa 342 unitats i el 0, 533. Els títols de segon nivell demanen a Alegreya SC 'lining', les seves xifres lnum, que fan l'alçada de les majúscules que les envolten. L'estil de taula demana 'tabular', el tnum de la font: les xifres conserven la forma elzeviriana i prenen totes la mateixa amplada, 450 unitats, així que una columna de preus es llegeix de dalt a baix. Amb 'lining-tabular' anirien a l'alçada de les majúscules (mira «Variants»).

#2 · Els comptes són taules de cinc columnes

script.js · línies 59–122al codi complet
// A row starting '=' is a total (header cells: a light rule above it), '+' heads a group.
const C = (content, align = 'left', extra = {}) => ({ content, align, ...extra });
function account(tsv) {
  const rows = tsv.replace(/^\n+|\n+$/g, '').split('\n').map((line) => {
    const total = line.startsWith('='), group = line.startsWith('+');
    const [item, dollar, amount, fraction, remark] = line.replace(/^[=+]/, '').split('\t');
    if (group) return [C(item, 'left', { colSpan: 5, isHeader: true }),
      ...[1, 2, 3, 4].map(() => C('', 'left', { hiddenBy: { row: -1, col: 0 } }))];
    const h = { isHeader: total };
    return [C(item, 'left', h), C(dollar ? '\\$' : '', 'right', h), // `$` alone opens maths
      C(amount ?? '', 'right', h), C(fraction ?? '', 'left', h), C(remark ?? '', 'left', h)];
  });
  rows.forEach((row, r) => row.forEach((cell) => cell.hiddenBy && (cell.hiddenBy.row = r)));
  return { rows, headerRowCount: 0, columnWidths: [34, 2.4, 8, 3.6, 35] };
}
const accounts = String.raw`=== house
Tablas,	$	8,03	½	casi todas de chabolas.
Tablillas de desecho para tejado y paredes,		4,00
Listones,		1,25
Dos ventanas de segunda mano con cristal,		2,43
Mil ladrillos viejos,		4,00
Dos barriles de cal,		2,40		Eso fue caro.
Pelo,		0,31		Más del que necesitaba.
Hierro para la repisa,		0,15
Clavos,		3,90
Bisagras y tornillos,		0,14
Pestillo,		0,10
Tiza,		0,01
Transporte,		1,40		Buena parte la llevé a cuestas.
=En total,	$	28,12	½
=== farm
	$	23,44
Descontando los gastos,		14,72	½
=Quedan,	$	8,71	½
=== food
Arroz,	$	1,73	½
Melaza,		1,73		La forma más barata del azúcar.
Harina de centeno,		1,04	¾
Harina de maíz,		0,99	¾	Más barata que la de centeno.
Cerdo,		0,22
+Todos los experimentos que fallaron:
Harina de trigo,		0,88		Cuesta más que la de maíz, en dinero y en trabajo.
Azúcar,		0,80
Manteca,		0,65
Manzanas,		0,25
Manzana seca,		0,22
Boniatos,		0,10
Una calabaza,		0,06
Una sandía,		0,02
Sal,		0,03
=== outgoes
Casa,	$	28,12	½
Granja, un año,		14,72	½
Comida, ocho meses,		8,74
Ropa, etc., ocho meses,		8,40	¾
Aceite, etc., ocho meses,		2,00
=En total,	$	61,99	¾
=== income
	$	23,44
Ganado como jornalero,		13,34
=En total,	$	36,78
`; // content.accounts.<lang>.md: one block per table
const tables = Object.fromEntries(accounts.split(/^=== /m).filter(Boolean)
  .map((block) => [block.slice(0, block.indexOf('\n')).trim(), block.slice(block.indexOf('\n'))]));

Els comptes de Thoreau es guarden com a TSV a content.accounts.es.md, un bloc per compte, de manera que l'edició castellana tradueix les partides i canvia el punt decimal per la coma sense tocar el codi. Cada fila porta la partida, el signe del dòlar, l'import, una fracció i una observació. Els mitjos i els quarts tenen columna pròpia: ½ fa 713 unitats i ¾, 689, més que una xifra tabular, i Alegreya no té espai de xifra per omplir els altres imports. Un total està fet de cel·les de capçalera, així que groupRules hi traça un filet fi a sobre, com l'impressor de Thoreau traçava una línia abans d'In all. El signe del dòlar s'escriu \$, perquè un $ sol obre una fórmula en una cel·la, igual que al text. El tipus de recurs account no porta número ni prefix de peu, i la seva col·locació per defecte és 'here', així que cada compte va on el presenta la frase de Thoreau.

#3 · L'obertura declara les seves xifres

script.js · línies 126–144al codi complet
const at = (to, edge, y, x = 0) => ({ anchor: { to, edge }, offset: { x: mm(x), y: mm(y) } });
// 'below' starts a text at the left edge of what it hangs from: the texts take the measure
// and start half the difference to the left of the vignette, so they centre on the page.
const centred = (to, y) => ({ ...at(to, 'below', y, (VIGNETTE - MEASURE) / 2),
  size: { width: mm(MEASURE) } });
const opener = { enabled: true, minHeight: pt(19 * LEAD), slot: { elements: [
  { kind: 'image', id: 'cabin', resourceId: 'cabin',
    placement: { ...at('container', 'top', 0), size: { width: mm(VIGNETTE) } } },
  { kind: 'text', id: 'kicker', content: '{attr.kicker}', fontFamily: LABEL, fontWeight: 500,
    fontSize: pt(7.5), letterSpacing: pt(1.5), textTransform: 'uppercase', color: col('accent'),
    align: 'center', placement: centred('#cabin', 6) },
  { kind: 'text', id: 'title', content: '{titleText}', fontFamily: CAPS, fontSize: pt(30),
    letterSpacing: pt(1.2), lineHeight: 1, color: col('ink'), align: 'center',
    placement: { ...at('#kicker', 'below', 2.5), size: { width: mm(MEASURE) } } },
  // A design text names its own family, so it states its figures too.
  { kind: 'text', id: 'dates', content: '{attr.dates}', fontFamily: CAPS, fontSize: pt(11),
    letterSpacing: pt(0.8), color: col('accent'), align: 'center', figureStyle: 'lining',
    placement: { ...at('#title', 'below', 2.5), size: { width: mm(MEASURE) } } },
] } };

Un text de disseny fixa la seva pròpia família, així que les xifres del cos no hi arriben. Concord, 1845–1847 va en Alegreya SC i demana 'lining' pel seu compte, com els títols. La vinyeta és el gravat de la portada de 1854, retallat i ajustat a negre sobre blanc; l'avanttítol, el títol i les dates prenen la mesura de la caixa i se centren a sota.

#4 · Capçaleres amb la secció a la pàgina senar

script.js · línies 148–161al codi complet
const head = (id, content, parity, edge, x, extra = {}) => ({
  kind: 'text', id, content, parity, pages: 'body', fontFamily: LABEL, fontSize: pt(7.5),
  fontWeight: 500, letterSpacing: pt(1.2), textTransform: 'uppercase', color: col('muted'),
  placement: { anchor: { to: 'page', edge }, offset: { x: mm(x), y: mm(13) } }, ...extra });
const folio = { fontFamily: TEXT, fontSize: pt(9.5), fontWeight: 400, letterSpacing: pt(0),
  color: col('ink') };
const header = { elements: [
  head('verso-folio', '{pageNumber}', 'even', 'top-left', OUTER, folio),
  head('verso-title', '{title}', 'even', 'top-left', OUTER + 8),
  head('recto-title', '{firstMark.h2}', 'odd', 'top-right', -(OUTER + 8)),
  head('recto-folio', '{pageNumber}', 'odd', 'top-right', -OUTER, folio),
] };
const footer = { elements: [head('drop-folio', '{pageNumber}', 'all', 'top', 0, {
  ...folio, pages: 'opener', placement: at('container', 'top', 8) })] };

La pàgina parella porta el títol del llibre, i la senar, la secció en curs, {firstMark.h2}, de manera que la pàgina 3 diu El campo de judías, 1845. Els folis van en Alegreya i conserven les xifres elzevirianes.

Pàgina 2: les xifres elzevirianes del compte de la casa tenen totes la mateixa amplada, i els cèntims s'alineen fins al total.

La recepta completa

Sandbox
// ═══ Postext Cookbook · Nº 176 · Old-style, lining and tabular figures ═══════════════
// https://postext.dev/en/cookbook/old-style-and-tabular-figures
// Code: MIT · Text: H. D. Thoreau, Walden (1854, public domain) · Vignette: 1854 title page (PD)
// Fonts: Alegreya, Alegreya SC, Alegreya Sans (SIL OFL 1.1) · Needs postext ≥ 1.65.0
// Thoreau's accounts from Walden. Each text style asks Alegreya for one kind of figures:
// old-style in the prose, lining in the small-capital headings, tabular in the accounts.
import {
  buildDocumentWithFonts, renderPageToCanvas, registerResourceImage, defaultResourceTypes,
} from 'https://esm.sh/postext';
import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf';

const LANG = 'es'; // @lang: the language of the sample document ('en' | 'es')
const RECIPE = 'old-style-and-tabular-figures';

// ─── 1 · Design ─────────────────────────────────────────────────────────────
const palette = {
  ink: '#221e1a', // text: a warm near-black
  accent: '#7d3a1f', // walnut: headings, kicker, rules of the opener
  rule: '#8a7f73', // the light rules of the accounts
  muted: '#6b6158', // running heads, the colophon
  paper: '#ffffff',
};
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' } },
];
const TEXT = 'Alegreya', CAPS = 'Alegreya SC', LABEL = 'Alegreya Sans';
const TRIM = [140, 216], INNER = 19, OUTER = 16; // mm: a trade paperback
const MEASURE = TRIM[0] - INNER - OUTER, VIGNETTE = 50; // mm
const LEAD = 14.5; // pt: the body leading, the grid the headings keep to

// #region answer: one figure style per text style
// Alegreya's own figures are old-style, so the prose asks for none: the cut Fontsource
// serves has no onum, and 'oldstyle' would change nothing (see the write-up).
const bodyText = {
  fontFamily: TEXT, fontSize: pt(10.8), lineHeight: pt(LEAD), color: col('ink'),
  boldColor: col('ink'), italicColor: col('ink'), referenceColor: col('ink'),
  textAlign: 'justify', firstLineIndent: mm(4.5), indentAfterHeading: false,
  hyphenation: { enabled: true }, optimalLineBreaking: true,
  avoidWidows: true, avoidOrphans: true, avoidRunts: true,
};
// Small capitals take lining figures (lnum), at the height of the capitals around them.
const section = { level: 2, fontFamily: CAPS, fontSize: pt(12.5), lineHeight: pt(LEAD),
  fontWeight: 400, letterSpacing: pt(0.6), color: col('accent'), figureStyle: 'lining',
  marginTop: pt(LEAD), marginBottom: pt(0) };
// The accounts: every figure on one width (tnum), so the cents stand in columns.
// 'tabular' keeps the font's form, old-style; 'lining-tabular' would set them at cap height.

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

#Compon els comptes en xifres de caixa alta

Un llibre de comptes o una llista de preus d'un llibre modern sol portar les xifres a l'alçada de les majúscules.

-  figureStyle: 'tabular', bodyFontFamily: TEXT, bodyFontSize: pt(9.8), bodyColor: col('ink'),
+  figureStyle: 'lining-tabular', bodyFontFamily: TEXT, bodyFontSize: pt(9.8), bodyColor: col('ink'),

#Compon els folis en xifres de caixa alta

Els folis en xifres de caixa alta casen amb capçaleres en majúscules.

-const folio = { fontFamily: TEXT, fontSize: pt(9.5), fontWeight: 400, letterSpacing: pt(0),
+const folio = { fontFamily: TEXT, fontSize: pt(9.5), fontWeight: 400, letterSpacing: pt(0),
+  figureStyle: 'lining',

Errors freqüents

  • Els fitxers latin que serveix Fontsource sovint deixen fora onum: Lora, EB Garamond, Source Serif 4, Crimson Pro, Newsreader i Literata només conserven pnum i tnum. Amb aquests fitxers, figureStyle: 'oldstyle' no canvia res i el text continua amb xifres de caixa alta. Tria una lletra amb xifres pròpies elzevirianes, com Alegreya, Gelasio o Cormorant Garamond, que afegeixen lnum per als títols, o carrega els fitxers complets de la foneria.
  • Un $ al Markdown o en una cel·la obre una fórmula en línia. Escriu \$14,72½ al text i \$ en una cel·la.

Crèdits

Text
  • The accounts and the passages around them from “Economy,” the first chapter of Walden; or, Life in the Woods (Boston: Ticknor and Fields, 1854) · Henry D. Thoreau · domini públic
  • The headnote, and the Spanish translation of the passages and the accounts · Ignacio Ferro · CC BY 4.0
Imatges
Fonts
Alegreya (SIL OFL 1.1) · Alegreya SC (SIL OFL 1.1) · Alegreya Sans (SIL OFL 1.1)
SandboxPDF