Vai al contenuto principale
Ricetta numero 176

Ricettario · Capitolo 2 · Caratteri e testo

Cifre old-style, maiuscole e tabellari

I conti di Thoreau in Walden: figureStyle dà cifre maiuscole ai titoli in maiuscoletto e cifre tabellari ai conti; la prosa conserva le cifre old-style.

In questa pagina
Output
Canvas · PDF
Livello
Intermedio
Postext
Provata con Postext 1.65.0
Richiede ≥ 1.65.0 · postext-pdf ≥ 1.65.0
Licenza
Aggiornata il 31 ott 2026
Codice MIT · Testo CC BY 4.0
  • Esempio in inglese: non c’è ancora un’edizione italiana
  • Formato 140 × 216 mm
  • 1 colonna
  • Alegreya 10,8/14,5
  • Alegreya SC
  • Alegreya SC@lnum
  • Alegreya Sans
  • Alegreya@tnum
  • 6 pagine
  • Livello
  • Postext 1.65.0
  • Impaginato in 124 ms
  • 160 righe di codice

In breve

Una piccola edizione dei conti di casa che Thoreau pubblicò in Walden. Le cifre del testo sono piccole come le minuscole, gli anni dei titoli alti come le maiuscole e le somme dei conti si allineano in colonna.

Che cosa comporrai

Una piccola edizione dei conti che Thoreau pubblicò nel primo capitolo di Walden: quanto gli costò la casa, quanto gli rese il campo di fagioli, che cosa mangiò in otto mesi. È composta su una pagina di 140 × 216 mm con la famiglia Alegreya, e l'apertura porta l'incisione del 1854 della capanna. Le cifre cambiano con il lavoro che fanno. Nella prosa, March, 1845 e $13.34 sono in cifre old-style, che salgono e scendono come le minuscole, così le date non sporgono dalla riga. I titoli sono in maiuscoletto, e i loro anni sono alti come le maiuscole. Nei conti ogni cifra ha la stessa larghezza, e i centesimi di tredici righe di assi, listelli e chiodi stanno uno sotto l'altro fino al totale.

Questa ricetta risponde a

  • Come compongo cifre old-style nel testo, cifre maiuscole nei titoli e cifre tabellari nelle tabelle?
  • Come compongo illustrazioni non numerate: fregi, vignette, loghi?

La risposta breve

script.js · righe 34–55nel codice completo
// 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),
};

Ingredienti

Tipo
Alegreya, Alegreya SC, Alegreya Sans (SIL OFL 1.1)
Risorse
  • 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), pubblico dominio)

Preparazione

#1 · Uno stile di cifre per ogni stile di testo

Il codice di questo passo è la risposta breve, più sopra. figureStyle chiede al carattere di uno stile le sue cifre OpenType (stili delle cifre). Il corpo non chiede nulla, perché le cifre proprie di Alegreya sono già old-style e proporzionali: l'1 è largo 342 unità e lo 0 533. I titoli di secondo livello chiedono ad Alegreya SC 'lining', le sue cifre lnum, alte come le maiuscole che le circondano. Lo stile di tabella chiede 'tabular', il tnum del carattere: le cifre mantengono la forma old-style e prendono tutte la stessa larghezza, 450 unità, così una colonna di prezzi si legge dall'alto in basso. Con 'lining-tabular' starebbero all'altezza delle maiuscole (vedi «Varianti»).

#2 · I conti sono tabelle di cinque colonne

script.js · righe 59–122nel codice completo
// 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
Boards,	$	8.03	½	mostly shanty boards.
Refuse shingles for roof sides,		4.00
Laths,		1.25
Two second-hand windows with glass,		2.43
One thousand old brick,		4.00
Two casks of lime,		2.40		That was high.
Hair,		0.31		More than I needed.
Mantle-tree iron,		0.15
Nails,		3.90
Hinges and screws,		0.14
Latch,		0.10
Chalk,		0.01
Transportation,		1.40		I carried a good part on my back.
=In all,	$	28.12	½
=== farm
	$	23.44
Deducting the outgoes,		14.72	½
=There are left,	$	8.71	½
=== food
Rice,	$	1.73	½
Molasses,		1.73		Cheapest form of the saccharine.
Rye meal,		1.04	¾
Indian meal,		0.99	¾	Cheaper than rye.
Pork,		0.22
+All experiments which failed:
Flour,		0.88		Costs more than Indian meal, both money and trouble.
Sugar,		0.80
Lard,		0.65
Apples,		0.25
Dried apple,		0.22
Sweet potatoes,		0.10
One pumpkin,		0.06
One watermelon,		0.02
Salt,		0.03
=== outgoes
House,	$	28.12	½
Farm one year,		14.72	½
Food eight months,		8.74
Clothing, etc., eight months,		8.40	¾
Oil, &c., eight months,		2.00
=In all,	$	61.99	¾
=== income
	$	23.44
Earned by day-labor,		13.34
=In all,	$	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'))]));

I conti di Thoreau sono conservati come TSV in content.accounts.en.md, un blocco per conto, e l'edizione spagnola traduce le voci e passa dal punto alla virgola decimale senza toccare il codice. Ogni riga ha la voce, il segno del dollaro, l'importo, una frazione e un'osservazione. Le metà e i quarti hanno una colonna propria: ½ è largo 713 unità e ¾ 689, più di una cifra tabellare, e Alegreya non ha uno spazio cifra con cui completare gli altri importi. Un totale è fatto di celle d'intestazione, quindi groupRules traccia sopra un filetto sottile, come lo stampatore di Thoreau tracciava una linea prima di In all. Il segno del dollaro si scrive \$, perché un $ da solo apre una formula in una cella come nel testo. Il tipo di risorsa account non ha numero né prefisso di didascalia, e il suo posizionamento predefinito è 'here': ogni conto sta dove la frase di Thoreau lo introduce.

#3 · L'apertura dichiara le proprie cifre

script.js · righe 126–144nel codice completo
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 testo di design stabilisce la propria famiglia, quindi le cifre del corpo non lo raggiungono. Concord, 1845–1847 è in Alegreya SC e chiede 'lining' per conto suo, come i titoli. La vignetta è l'incisione del frontespizio del 1854, ritagliata e portata a nero su bianco; occhiello, titolo e date prendono la giustezza e si centrano sotto di essa.

#4 · Testatine con la sezione sulla pagina dispari

script.js · righe 148–161nel codice completo
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 pagina pari porta il titolo del libro, la dispari la sezione in corso, {firstMark.h2}: la pagina 3 dice The Bean-Field, 1845. I folii sono in Alegreya e conservano le cifre old-style.

Pagina 2: le cifre old-style del conto della casa hanno tutte la stessa larghezza, e i centesimi si allineano fino al totale.

La ricetta 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 = 'en'; // @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.

Lo script.js composto funziona così com’è: incollalo nello script modulo di qualsiasi pagina, oppure apri la ricetta su CodePen. Cartella della ricetta su GitHub ↗ (si apre in una nuova scheda)

Varianti

#Componi i conti in cifre maiuscole

Un libro contabile o un listino prezzi in un libro moderno porta spesso le cifre all'altezza delle maiuscole.

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

#Componi i folii in cifre maiuscole

Folii in cifre maiuscole si accordano con testatine in maiuscolo.

-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',

Errori frequenti

  • I file latin serviti da Fontsource spesso lasciano fuori onum: Lora, EB Garamond, Source Serif 4, Crimson Pro, Newsreader e Literata tengono solo pnum e tnum. Con questi file figureStyle: 'oldstyle' non cambia nulla e il testo resta in cifre maiuscole. Scegli un carattere le cui cifre proprie siano old-style, come Alegreya, Gelasio o Cormorant Garamond, che aggiungono lnum per i titoli, oppure carica i file completi della fonderia.
  • Un $ nel Markdown o in una cella apre una formula in linea. Scrivi \$14.72½ nel testo e \$ in una cella.

Crediti

Testo
  • 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 · pubblico dominio
  • The headnote, and the Spanish translation of the passages and the accounts · Ignacio Ferro · CC BY 4.0
Immagini
Font
Alegreya (SIL OFL 1.1) · Alegreya SC (SIL OFL 1.1) · Alegreya Sans (SIL OFL 1.1)
SandboxPDF