En bref
Un petit recueil pour chanter autour d'une table. Chaque chanson s'écrit en texte dans une notation musicale appelée ABC, et Postext dessine la portée, les notes, les accords de guitare et les paroles sous les notes.
Ce que vous allez composer
Songs for the Long Table, un recueil de chansons de poche au format A5 : une page de titre garance, un mot aux chanteurs avec la table des matières, trois chansons et des notes sur l'origine de chacune. Chaque chanson s'ouvre sous un grand numéro garance, un titre en Fraunces et une ligne de crédits en petites capitales. Dessous, la mélodie court sur une portée de 5,5 mm en Leland, avec les accords de guitare au-dessus des mesures et le premier couplet sous les notes en Spectral, le caractère de texte du livre. Les couplets suivants se rangent sur deux colonnes, et le chanteur n'a qu'à descendre depuis la dernière mesure. Amazing Grace, dont les longs vers reviendraient à la ligne dans une colonne, pose ses strophes l'une sous l'autre, centrées. L'édition espagnole est un recueil d'anniversaire avec trois chansons plus courtes, deux par page.
Cette recette répond à
- Comment composer un recueil de chansons avec la mélodie, les paroles sous les notes et les accords ?
La réponse courte
// 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".
Ingrédients
- Fonctionnalités
- Notation musicaleStyle de partitionVers ligne à ligneOuvertures composéesAttributs de titreTitres numérotésStyles de titreChapitres non numérotésCouvertures, pages de titre et colophonsMétadonnées du documentTable des matièresTitres courants et foliosTitres courants selon le rôle de la pageStyles de paragrapheMarges en miroirPalette de couleurs sémantiqueCouleur du papierTexte, filets et boîtes dans les maquettes de pageExport PDF
- Utilise aussi
- Colonnes dans un encadré ou dans le texteListings de codePolices intégrées au PDFTitres courants par section
- Typographie
- Spectral, Spectral SC, Fraunces (SIL OFL 1.1)
- Ressources
- Aucune : chaque image est dessinée en code
Préparation
#1 · Écrire la chanson, définir la partition une seule fois
Le style de partition est la réponse courte ci-dessus. Dans le Markdown, chaque chanson est un bloc ```abc : les lignes d'en-tête donnent la mesure, la durée de note de référence et la tonalité ; un nom d'accord entre guillemets doubles ("D7"A) s'imprime au-dessus de la note qu'il précède ; une ligne w: sous la musique place une syllabe sous chaque note, séparées par des traits d'union. Un air avec couplet et refrain tient en deux lignes de musique, chacune avec sa ligne w:. La taille de la portée, la police musicale, le caractère des paroles, les numéros de mesure et l'espace entre les systèmes viennent de scoreStyle, si bien que les trois chansons s'accordent et que les blocs ne contiennent que de la musique.
#2 · Ouvrir chaque chanson sous son numéro et ses crédits
// # 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 } };
La chanson est un titre de premier niveau avec un attribut credit, et son design en tire le numéro, le titre et la ligne de crédits. minHeight donne à chaque chanson la même tête de 21 mm, de sorte que les portées commencent à la même hauteur sur chaque page. Les chansons s'enchaînent avec trois lignes d'espace au-dessus de chaque titre, et une partition n'est jamais coupée avant son deuxième système (minSystemsAtBreak: 2) : les chansons anglaises remplissent chacune une page, et deux des courtes chansons espagnoles en partagent une.
#3 · Mettre les autres couplets sur deux colonnes
// :::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) };
Chaque strophe est un bloc :::verse : ses vers se coupent là où le poète les a coupés, et le deuxième et le quatrième rentrent d'un cadratin. Un groupe :::columns{count=2 gap=4mm} les place côte à côte en 9,4 pt. Comptez d'abord les caractères. Les vers de Burns tiennent dans une colonne de 55 mm, le long mètre de Newton non, alors Amazing Grace garde un seul bloc :::verse centré et laisse les lignes vides séparer ses strophes.
#4 · Garder les éléments fixes discrets
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),
] };
Les titres courants figurent sur toutes les pages qu'occupent les chansons, le titre du livre au verso et la chanson au recto, avec le folio dans le garance des numéros de chanson. La page de titre et le mot aux chanteurs les suppriment par un header vide dans leurs styles de titre.
La recette complète
// ═══ 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
Le script.js composé s’exécute tel quel : collez-le dans le script de module de n’importe quelle page, ou ouvrez la recette sur CodePen. Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)
Variantes
#Graver en Bravura
Bravura a des têtes de note plus épaisses et l'allure d'une planche gravée ; elle convient à un recueil de cantiques composé dans un caractère de texte plus sombre.
- musicFont: 'Leland', // lighter noteheads than Bravura, close to Spectral's colour
+ musicFont: 'Bravura',#Numéroter les mesures
Une chorale répète d'après les numéros de mesure ; imprimez-en un au début de chaque système.
- barNumbers: 'none', // a table of singers counts verses, not bars
+ barNumbers: 'system',Erreurs fréquentes
Erreur fréquente
Un style de titre hérite du saut de page de son niveau
Une entrée headingStyles reprend de son niveau de titre chaque champ qu’elle omet, breakBefore compris. Une page de table des matières ou un colophon mis en forme sur un H1 après un :::pagebreak hérite de la parité 'odd' et atterrit derrière une page blanche. Donnez à un tel style breakBefore: { enabled: false }. Styles de titre →
- Le lecteur ABC de Verovio ignore les marques de tenue
_et*d'une lignew:: chaque note prend la syllabe suivante. Sous la deuxième note d'une liaison, écrivez une espace insécable (U+00A0) comme syllabe à part entière ; elle n'imprime rien. Les notes liées par une liaison de prolongation ne prennent pas de syllabe. ~réunit deux syllabes sous une même note (de~a-trás), mais le graveur les imprime avec une espace ordinaire, sans signe de liaison.- Écrivez les noms d'accords sans ♭ ni ♯ quand c'est possible : la plupart des caractères de texte n'ont pas ces signes et la page se rabat sur une police système. Choisissez des tonalités dont les accords sont naturels (G, C, D7, Em), ou écrivez « si bémol » dans le texte.
Crédits
- Recette
- Ignacio Ferro
- Texte
- Amazing Grace: words (1779, five of the six stanzas, in the Olney Hymns spelling) · John Newton · domaine public
- 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 · domaine public
- Oh My Darling, Clementine: words and tune (Oliver Ditson, Boston, 1884) · Percy Montrose · domaine public
- Auld Lang Syne: words (1788) and the Scots tune of George Thomson's Select Songs of Scotland (1799) · Robert Burns; traditional · domaine public
- Cumpleaños feliz: the tune of Good Morning to All (Song Stories for the Kindergarten, Chicago, 1893); Spanish words traditional · Mildred J. Hill; traditional · domaine public
- Martinillo: the French tune of Frère Jacques (18th century) with the traditional Spanish words · Traditional · domaine public
- La cucaracha: tune, chorus and verse as in the Spanish Wikipedia transcription; two traditional Mexican coplas · Traditional · domaine public
- The preface, the notes on the songs and the chord symbols · Ignacio Ferro · CC BY 4.0
- Polices
- Spectral (SIL OFL 1.1) · Spectral SC (SIL OFL 1.1) · Fraunces (SIL OFL 1.1)
Modifier ce texte ↗ (s’ouvre dans un nouvel onglet)Dossier de la recette sur GitHub ↗ (s’ouvre dans un nouvel onglet)


