Aller au contenu principal
Recette numéro 164

Recettes · Chapitre 9 · Publications complètes

Un recueil de chansons avec mélodie, paroles et accords

Chaque chanson est un bloc ABC : la mélodie, les accords sur la portée et le premier couplet sous les notes, gravés à la largeur de colonne par un style.

Sur cette page
Sortie
Canvas · PDF
Postext
Testé avec Postext 1.54.0
Nécessite ≥ 1.54.0 · postext-pdf ≥ 1.54.0
Licence
Mis à jour le 22 oct. 2026
Code MIT · Texte CC BY 4.0

p. 2–3 sur 6

  • Exemple en anglais : pas encore d’édition française
  • Format 148 × 210 mm
  • 1 colonne
  • Spectral 10,3/14
  • Fraunces
  • Spectral SC
  • 6 pages
  • Niveau
  • Postext 1.54.0
  • Mis en page en 300 ms
  • 164 lignes de code

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

script.js · lignes 33–50dans le code complet
// 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

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

script.js · lignes 66–81dans le code complet
// # 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

script.js · lignes 54–62dans le code complet
// :::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

script.js · lignes 119–131dans le code complet
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

Sandbox
// ═══ 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 ligne w: : 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

Texte
Polices
Spectral (SIL OFL 1.1) · Spectral SC (SIL OFL 1.1) · Fraunces (SIL OFL 1.1)
SandboxPDF