Pular para o conteúdo principal
Receita número 176

Receitas · Capítulo 2 · Tipo e texto

Algarismos de estilo antigo, alinhados e tabulares

As contas de Thoreau em Walden: figureStyle dá algarismos alinhados aos títulos em versaletes e tabulares às contas; a prosa mantém os de estilo antigo.

Nesta página
Saída
Canvas · PDF
Postext
Testada com o Postext 1.65.0
Requer ≥ 1.65.0 · postext-pdf ≥ 1.65.0
Licença
Atualizada em 31 de out. de 2026
Código MIT · Texto CC BY 4.0
  • Amostra em inglês: ainda sem edição em português
  • Refile 140 × 216 mm
  • 1 coluna
  • Alegreya 10,8/14,5
  • Alegreya SC
  • Alegreya SC@lnum
  • Alegreya Sans
  • Alegreya@tnum
  • 6 páginas
  • Nível
  • Postext 1.65.0
  • Diagramado em 124 ms
  • 160 linhas de código

Em poucas palavras

Uma pequena edição das contas domésticas que Thoreau publicou em Walden. Os números do texto são pequenos como minúsculas, os anos dos títulos têm a altura das maiúsculas e as somas das contas se alinham em coluna.

O que você vai compor

Uma pequena edição das contas que Thoreau publicou no primeiro capítulo de Walden: quanto lhe custou a casa, quanto rendeu o campo de feijão, o que comeu em oito meses. Ela é composta numa página de 140 × 216 mm na família Alegreya, com a gravura de 1854 da cabana na abertura. Os algarismos mudam conforme a função. Na prosa, March, 1845 e $13.34 vão em algarismos de estilo antigo, que sobem e descem como as minúsculas, e as datas não saltam da linha. Os títulos são versaletes, e seus anos têm a altura das maiúsculas. Nas contas todos os algarismos têm a mesma largura, e os centavos de treze linhas de tábuas, sarrafos e pregos ficam um embaixo do outro até o total.

Esta receita responde a

  • Como componho algarismos de estilo antigo no texto, algarismos alinhados nos títulos e algarismos tabulares nas tabelas?
  • Como componho ilustrações sem numeração: ornamentos, vinhetas, logotipos?

A resposta curta

script.js · linhas 34–55no código 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),
};

Ingredientes

Tipografia
Alegreya, Alegreya SC, Alegreya Sans (SIL OFL 1.1)
Materiais
  • 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), domínio público)

Preparo

#1 · Um estilo de algarismos por estilo de texto

O código deste passo é a resposta curta, mais acima. figureStyle pede à fonte de um estilo seus algarismos OpenType (estilos de algarismos). O corpo não pede nada, porque os algarismos próprios da Alegreya já são de estilo antigo e proporcionais: o 1 tem 342 unidades e o 0, 533. Os títulos de segundo nível pedem à Alegreya SC 'lining', seus algarismos lnum, da altura das maiúsculas ao redor. O estilo de tabela pede 'tabular', o tnum da fonte: os algarismos mantêm a forma de estilo antigo e ficam todos com a mesma largura, 450 unidades, e uma coluna de preços se lê de cima a baixo. Com 'lining-tabular' eles ficariam na altura das maiúsculas (veja “Variações”).

#2 · As contas são tabelas de cinco colunas

script.js · linhas 59–122no código 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'))]));

As contas de Thoreau ficam em TSV em content.accounts.en.md, um bloco por conta, e a edição espanhola traduz os itens e troca o ponto decimal pela vírgula sem mexer no código. Cada linha tem o item, o cifrão, o valor, uma fração e uma observação. As metades e os quartos têm coluna própria: ½ tem 713 unidades e ¾, 689, mais que um algarismo tabular, e a Alegreya não tem espaço de algarismo para completar os outros valores. Um total é feito de células de cabeçalho, então groupRules traça um fio fino acima dele, como o impressor de Thoreau traçava uma linha antes de In all. O cifrão se escreve \$, porque um $ sozinho abre uma fórmula numa célula, como no texto. O tipo de recurso account não tem número nem prefixo de legenda, e sua colocação padrão é 'here': cada conta fica onde a frase de Thoreau a apresenta.

#3 · A abertura declara seus próprios algarismos

script.js · linhas 126–144no código 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) } } },
] } };

Um texto de design define a própria família, então os algarismos do corpo não chegam até ele. Concord, 1845–1847 está em Alegreya SC e pede 'lining' por conta própria, como os títulos. A vinheta é a gravura da folha de rosto de 1854, recortada e ajustada para preto sobre branco; o antetítulo, o título e as datas tomam a largura da mancha e se centralizam embaixo dela.

#4 · Cabeços com a seção na página ímpar

script.js · linhas 148–161no código 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) })] };

A página par traz o título do livro, e a ímpar, a seção em curso, {firstMark.h2}: a página 3 diz The Bean-Field, 1845. Os fólios vão em Alegreya e mantêm os algarismos de estilo antigo.

Página 2: os algarismos de estilo antigo da conta da casa têm todos a mesma largura, e os centavos se alinham até o total.

A receita 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.

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

#Componha as contas em algarismos alinhados

Um livro-caixa ou uma lista de preços num livro moderno costuma pôr os algarismos na altura das maiúsculas.

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

#Componha os fólios em algarismos alinhados

Fólios em algarismos alinhados combinam com cabeços em maiúsculas.

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

Erros comuns

  • Os arquivos latin que a Fontsource serve muitas vezes deixam onum de fora: Lora, EB Garamond, Source Serif 4, Crimson Pro, Newsreader e Literata só mantêm pnum e tnum. Com esses arquivos, figureStyle: 'oldstyle' não muda nada e o texto continua com algarismos alinhados. Escolha uma fonte cujos algarismos próprios sejam de estilo antigo, como Alegreya, Gelasio ou Cormorant Garamond, que trazem lnum para os títulos, ou carregue os arquivos completos da fundição.
  • Um $ no Markdown ou numa célula abre uma fórmula em linha. Escreva \$14.72½ no texto e \$ numa célula.

Créditos

Texto
  • 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 · domínio público
  • The headnote, and the Spanish translation of the passages and the accounts · Ignacio Ferro · CC BY 4.0
Imagens
Fontes
Alegreya (SIL OFL 1.1) · Alegreya SC (SIL OFL 1.1) · Alegreya Sans (SIL OFL 1.1)
SandboxPDF