Em poucas palavras
Um pequeno cancioneiro para cantar em volta da mesa. Cada canção é escrita como texto simples numa notação musical chamada ABC, e o Postext desenha a pauta, as notas, os acordes de violão e a letra sob as notas.
O que você vai compor
Songs for the Long Table, um cancioneiro de bolso em formato A5: uma folha de rosto cor de garança, um recado para quem canta com o sumário, três canções e as notas sobre a origem de cada uma. Cada canção abre sob um número grande cor de garança, um título em Fraunces e uma linha de créditos em versaletes. Abaixo, a melodia corre numa pauta de 5,5 mm em Leland, com os acordes de violão sobre os compassos e a primeira estrofe sob as notas em Spectral, a fonte de texto do livro. As demais estrofes ficam em duas colunas, e quem canta lê direto para baixo a partir do último compasso. Amazing Grace, cujos versos longos quebrariam numa coluna, põe as estrofes uma sob a outra, centralizadas. A edição em espanhol é um cancioneiro de aniversário com três canções mais curtas, duas por página.
Esta receita responde a
- Como faço um cancioneiro com a melodia, a letra sob as notas e as cifras dos acordes?
A resposta curta
// A song is an ```abc fence in the Markdown: the melody, its chords written "G" before the note
// they fall on, and the first verse on a w: line under it. The look is set here, once.
const scoreStyle = {
staffSize: mm(5.5), // a songbook rastral; the words under it come out at about 8 pt
musicFont: 'Leland', // lighter noteheads than Bravura, close to Spectral's colour
textFont: TEXT, // words and chord names in the text face, not the engraver's Times
spacing: 1, // the engraver's own: five or six bars of 3/4 to a system on this measure
barNumbers: 'none', // a table of singers counts verses, not bars
systemGap: mm(4.5), // room for the chord names between one system's words and the next
marginTop: pt(4),
marginBottom: pt(LEAD),
color: col('ink'),
minSystemsAtBreak: 2, // never a lone system at a page foot or head
};
// Two habits of Verovio's ABC reader shape the w: lines. Every sung note takes the next
// syllable in order: the `_` and `*` holds are read as nothing, so the second note of a
// slurred pair (B/G/ under "-ing") gets a no-break space, which prints nothing. A tied note
// takes none. `~` joins two syllables on one note: "de~a-trás".
Ingredientes
- Funcionalidades
- Notação musicalEstilo de partituraVerso linha a linhaAberturas desenhadasAtributos de títuloTítulos numeradosEstilos de títuloCapítulos sem númeroCapas, folhas de rosto e colofõesMetadados do documentoSumárioCabeços e fóliosCabeços por tipo de páginaEstilos de parágrafoMargens espelhadasPaleta de cores semânticaCor do papelTextos, fios e caixas nos designs de páginaExportação para PDF
- Também usa
- Colunas num boxe ou no textoListagens de códigoFontes incorporadas ao PDFCabeços por seção
- Tipografia
- Spectral, Spectral SC, Fraunces (SIL OFL 1.1)
- Materiais
- Nenhum: todas as imagens são desenhadas em código
Preparo
#1 · Escreva a canção e defina a partitura uma única vez
O estilo de partitura é a resposta curta acima. No Markdown, cada canção é um bloco ```abc: as linhas de cabeçalho dão o compasso, a figura de referência e a tonalidade; o nome de um acorde entre aspas duplas ("D7"A) sai impresso sobre a nota que ele antecede; uma linha w: sob a música põe uma sílaba sob cada nota, separadas por hifens. Uma melodia com estrofe e refrão são duas linhas de música, cada uma com sua linha w:. O tamanho da pauta, a fonte musical, a fonte da letra, os números de compasso e o espaço entre os sistemas vêm de scoreStyle, de modo que as três canções combinam e os blocos levam só música.
#2 · Abra cada canção sob seu número e seus créditos
// # Amazing Grace {credit="Words John Newton, 1779 · Tune New Britain, American, 1835"}
// The songs run on, three lines apart: a short song shares its page with the next one.
const at = (to, edge, x = 0, y = 0) => ({ anchor: { to, edge }, offset: { x: mm(x), y: mm(y) } });
const text = (id, content, font, size, color, placement, extra = {}) => ({ kind: 'text', id,
content, fontFamily: font, fontSize: pt(size), color: col(color), align: 'left', placement,
...extra });
const songHead = { enabled: true, minHeight: mm(21), slot: { elements: [
text('number', '{number}', DISPLAY, 26, 'madder', at('container', 'top-left', 0, 1),
{ fontWeight: 600, lineHeight: 1 }),
text('title', '{titleText}', DISPLAY, 21, 'ink', { ...at('container', 'top-left', 12, 2),
size: { width: mm(100) } }, { fontWeight: 600, lineHeight: 1.05 }),
text('credit', '{attr.credit}', LABEL, 8.4, 'madder', { ...at('#title', 'below', 0, 2.2),
size: { width: mm(100) } }, { fontWeight: 600, letterSpacing: pt(0.6) }),
] } };
const songs = { level: 1, numberingTemplate: '{1}', advancedDesign: songHead,
marginTop: pt(LEAD * 3), marginBottom: pt(0), breakBefore: { enabled: false } };
A canção é um título de primeiro nível com um atributo credit, e o design dele compõe com isso o número, o título e a linha de créditos. minHeight dá a todas as canções a mesma cabeça de 21 mm, e assim as pautas começam na mesma altura em cada página. As canções vêm em sequência, com três linhas de espaço sobre cada título, e uma partitura nunca é cortada antes do segundo sistema (minSystemsAtBreak: 2): as canções em inglês ocupam uma página cada, e duas das canções curtas em espanhol dividem uma.
#3 · Ponha as outras estrofes em duas colunas
// :::columns{count=2} holds one :::verse block per stanza; each line of the stanza is a
// line of Markdown, the turned lines indented two spaces (one em). A hymn in long lines
// (Amazing Grace) drops the columns: its stanzas stand one under another, centred.
const verse = { id: 'verse', fontSize: pt(9.4), lineHeight: pt(13), hyphenation: false,
marginBottom: pt(13 / 2) };
const chorus = { id: 'chorus', fontSize: pt(9.4), lineHeight: pt(13), italic: true,
hyphenation: false, marginBottom: pt(LEAD / 2) };
const colophon = { id: 'colophon', fontFamily: LABEL, fontSize: pt(7.8), lineHeight: pt(11),
color: col('muted'), textAlign: 'left', firstLineIndent: pt(0), marginTop: pt(LEAD * 2) };
Cada estrofe é um bloco :::verse, então os versos quebram onde o poeta os quebrou e o segundo e o quarto entram um eme. Um grupo :::columns{count=2 gap=4mm} as coloca lado a lado em 9,4 pt. Conte os caracteres antes: os versos de Burns cabem numa coluna de 55 mm, o metro longo de Newton não, e por isso Amazing Grace mantém um único bloco :::verse centralizado e deixa que as linhas em branco separem as estrofes.
#4 · Deixe discretos os elementos fixos
const head = (id, content, parity, edge, x, style = {}) => ({
kind: 'text', id, content, parity, pages: 'all', // a song's first page carries them too
fontFamily: LABEL, fontSize: pt(8.4), fontWeight: 600, letterSpacing: pt(0.9),
color: col('muted'), ...style,
placement: { anchor: { to: 'page', edge }, offset: { x: mm(x), y: mm(12.5) } },
});
const folio = { fontFamily: TEXT, fontWeight: 600, letterSpacing: pt(0), color: col('madder') };
const header = { elements: [
head('verso-folio', '{pageNumber}', 'even', 'top-left', OUTER, folio),
head('verso-title', '{title}', 'even', 'top-left', OUTER + 8),
head('recto-song', '{chapterTitle}', 'odd', 'top-right', -(OUTER + 8)),
head('recto-folio', '{pageNumber}', 'odd', 'top-right', -OUTER, folio),
] };
Os cabeçalhos estão em todas as páginas que as canções alcançam, o título do livro na página par e a canção na ímpar, com o fólio na cor de garança dos números das canções. A folha de rosto e o recado para quem canta os removem com um header vazio nos seus estilos de título.
A receita completa
// ═══ Postext Cookbook · Nº 164 · Songbook: melody, words under the notes, chords ═══════
// https://postext.dev/en/cookbook/songbook-melody-words-chords
// Code: MIT · Words and tunes: public domain (see the notes in each edition) · Prose: CC BY 4.0
// Fonts: Spectral, Spectral SC, Fraunces (SIL OFL 1.1); Leland (music) · Needs postext ≥ 1.54.0
import {
buildDocumentWithFonts, renderPageToCanvas, initMusicEngine,
} 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 = 'songbook-melody-words-chords';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
const palette = { // every colour in the config links to one of these
ink: '#211e1b', // text and notes: a warm near-black
madder: '#8a3324', // the one accent: song numbers, the title page, credit lines
tint: '#f1e7d8', // the subtitle on the madder ground (8.2:1)
rule: '#cbbca6', // hairlines
muted: '#675e55', // running heads, notes and the colophon (5.9:1 on the paper)
paper: '#fbf8f1', // a cream stock
};
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' } })),
// The engine's defaults link to 'main-color': point it at the accent, so nothing prints blue.
{ id: 'main-color', name: 'madder (defaults)', value: { hex: palette.madder, model: 'hex' } },
];
const [TEXT, LABEL, DISPLAY] = ['Spectral', 'Spectral SC', 'Fraunces'];
const LEAD = 14; // pt: the body's leading
const OUTER = 15; // mm: the outer margin, where the running heads and folios align
// #region answer: the score style: a 5 mm staff in Leland, the words in the book's face
// A song is an ```abc fence in the Markdown: the melody, its chords written "G" before the note
// they fall on, and the first verse on a w: line under it. The look is set here, once.
const scoreStyle = {
staffSize: mm(5.5), // a songbook rastral; the words under it come out at about 8 pt
musicFont: 'Leland', // lighter noteheads than Bravura, close to Spectral's colour
textFont: TEXT, // words and chord names in the text face, not the engraver's Times
spacing: 1, // the engraver's own: five or six bars of 3/4 to a system on this measure
barNumbers: 'none', // a table of singers counts verses, not bars
systemGap: mm(4.5), // room for the chord names between one system's words and the next
marginTop: pt(4),
marginBottom: pt(LEAD),
color: col('ink'),
minSystemsAtBreak: 2, // never a lone system at a page foot or head
};
// Two habits of Verovio's ABC reader shape the w: lines. Every sung note takes the next
// syllable in order: the `_` and `*` holds are read as nothing, so the second note of a
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
#Grave em Bravura
Bravura tem cabeças de nota mais grossas e o aspecto de uma chapa gravada; combina com um hinário composto numa fonte de texto mais escura.
- musicFont: 'Leland', // lighter noteheads than Bravura, close to Spectral's colour
+ musicFont: 'Bravura',#Numere os compassos
Um coro ensaia pelos números de compasso; imprima um no início de cada sistema.
- barNumbers: 'none', // a table of singers counts verses, not bars
+ barNumbers: 'system',Erros comuns
Erro comum
Um estilo de título herda a quebra de página do seu nível
Uma entrada de headingStyles recebe do seu nível de título todos os campos que não define, inclusive breakBefore. Um sumário ou um colofão com estilo sobre um H1 depois de um :::pagebreak herda a paridade 'odd' e cai depois de uma página em branco. Dê a esse estilo breakBefore: { enabled: false }. Estilos de título →
- O leitor ABC do Verovio ignora as marcas de sustentação
_e*de uma linhaw:: cada nota pega a sílaba seguinte. Sob a segunda nota de uma ligadura de expressão, escreva um espaço não separável (U+00A0) como sílaba própria; ele não imprime nada. Notas unidas por ligadura de valor não levam sílaba. ~junta duas sílabas sob uma mesma nota (de~a-trás), mas o gravador as imprime com um espaço comum, sem o sinal de elisão.- Escreva as cifras sem ♭ nem ♯ quando puder: a maioria das fontes de texto não tem esses sinais e a página recorre a uma fonte do sistema. Escolha tonalidades com acordes naturais (G, C, D7, Em) ou escreva “si bemol” no texto.
Créditos
- Receita
- Ignacio Ferro
- Texto
- Amazing Grace: words (1779, five of the six stanzas, in the Olney Hymns spelling) · John Newton · domínio público
- Amazing Grace: the tune New Britain (Southern Harmony, 1835), melody as in E. O. Excell's setting of 1900, chord symbols added · Traditional American; William Walker; Edwin O. Excell · domínio público
- Oh My Darling, Clementine: words and tune (Oliver Ditson, Boston, 1884) · Percy Montrose · domínio público
- Auld Lang Syne: words (1788) and the Scots tune of George Thomson's Select Songs of Scotland (1799) · Robert Burns; traditional · domínio público
- Cumpleaños feliz: the tune of Good Morning to All (Song Stories for the Kindergarten, Chicago, 1893); Spanish words traditional · Mildred J. Hill; traditional · domínio público
- Martinillo: the French tune of Frère Jacques (18th century) with the traditional Spanish words · Traditional · domínio público
- La cucaracha: tune, chorus and verse as in the Spanish Wikipedia transcription; two traditional Mexican coplas · Traditional · domínio público
- The preface, the notes on the songs and the chord symbols · Ignacio Ferro · CC BY 4.0
- Fontes
- Spectral (SIL OFL 1.1) · Spectral SC (SIL OFL 1.1) · Fraunces (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)


