En bref
Un chapitre d’un manuel de théorie musicale sur la fin des phrases. Les exemples s’écrivent en courtes lignes de texte dans le chapitre, et Postext les dessine en portées et en notes ; le plus long continue sur la page suivante.
Ce que vous allez composer
Le chapitre 5 d’un cours d’harmonie au clavier, en 180 × 250 mm et en Libre Caslon, consacré aux cinq cadences : parfaite, imparfaite, demi-cadence, plagale et rompue. Chaque cadence reçoit deux courts paragraphes et un exemple à trois voix, avec ses chiffres romains sous la portée, écrit en ABC directement dans le Markdown. Le chapitre se termine par Greensleeves en la mineur, un chiffre au-dessus de chaque mesure, et cette mélodie est trop longue pour la place qui reste en page 3 : elle y pose trois systèmes et met les deux derniers en tête de la page 4, coupée entre deux systèmes comme un paragraphe se coupe entre deux lignes. La taille de la portée, la police musicale et l’espacement sont réglés une seule fois dans la configuration : les cinq exemples et la mélodie partagent ainsi le même aspect.
Cette recette répond à
- Comment mettre des exemples musicaux dans le texte d'un manuel, écrits en notation ?
La réponse courte
// Each ```abc fence in the chapter is engraved at the width of the text column and cut
// into systems. The style is set once here; the Markdown only holds the notation.
const scoreStyle = {
staffSize: mm(5.5), // a textbook's rastral: examples read at arm's length on a desk
musicFont: 'Bravura', // the traditional engraved look, heavy enough beside Caslon
textFont: 'Libre Caslon Text', // the Roman numerals of `w:` lines, in the text face
spacing: 1.6, // air between the chords: an example reads as a progression, not a cluster
barNumbers: 'system',
systemGap: mm(4),
marginTop: pt(LEAD / 2),
marginBottom: pt(LEAD / 2),
color: col('ink'),
// A long example runs on into the next page between two systems, never leaving one
// system alone at the foot of a page or at the head of the next.
minSystemsAtBreak: 2,
};
Ingrédients
- Fonctionnalités
- Notation musicaleStyle de partitionOuvertures composéesAttributs de titreTitres courants et foliosMarges en miroirTitres courants selon le rôle de la pageEncadrésStyles de paragraphePalette de couleurs sémantiqueVeuves, orphelines et fins de paragraphe trop courtesExport PDF
- Typographie
- Libre Caslon Text, Libre Caslon Display, Libre Franklin (SIL OFL 1.1)
- Ressources
- Aucune : chaque image est dessinée en code
Préparation
#1 · Écrire l’exemple là où le texte en a besoin
Un bloc marqué abc contient la notation, et le texte reprend après lui. L:1/2 fait de chaque accord sans durée une blanche, [Bdg] empile trois notes dans une seule voix, et une ligne w: place un mot sous chaque accord, ici les chiffres romains. L’attribut alt est ce que disent un lecteur d’écran et le PDF balisé à la place de l’image.
```abc {alt="Cadence parfaite en sol majeur : I, IV, V, I"}
X:1
M:4/4
L:1/2
K:G
[Bdg] [ceg] | [Adf] [Bdg] |]
w: I IV V I
```#2 · Donner à chaque partition l’allure du livre
La réponse courte contient toute la maquette de la musique : une portée de 5,5 mm, comme dans les manuels d’harmonie pour des exemples lus au clavier, Bravura à côté du texte en Caslon, et les chiffres dans le caractère du texte au lieu du Times du graveur. spacing: 1.6 étale quatre accords en blanches sur un tiers de la justification, pour que la progression se lise accord par accord. Le même réglage décide combien de mesures de Greensleeves tiennent sur un système : trois, dans une justification de 125 mm.
#3 · Laisser un long exemple continuer
minSystemsAtBreak: 2 garde Greensleeves lisible au changement de page. La mélodie sort en cinq systèmes ; trois tiennent au pied de la page 3, deux passent donc à la page 4, et aucune page ne reste avec un seul système. Une partition de moins de quatre systèmes passe entière à la page suivante, comme le feraient les courts exemples de cadences.
#4 · Démarrer le graveur avant la composition
// The engraver (Verovio) loads only for books with music: start it before the build,
// or every score is laid out as a grey placeholder box.
await initMusicEngine();
const doc = await buildDocumentWithFonts({ markdown }, config, kitFonts(FONTS));
showPages(doc, { title: t({ en: 'Harmony textbook', es: 'Manual de armonía' }) });
// The PDF draws every system as vector paths, the numerals in the embedded text face.
offerPdf(() => renderToPdf(doc, { fontProvider: fontsourceProvider }), `${RECIPE}.pdf`);
Verovio pèse environ 3,7 Mo de WebAssembly : le moteur ne le charge donc que si vous le demandez. Sans initMusicEngine(), la mise en page se fait quand même, et chaque partition est un rectangle gris de la bonne taille. renderToPdf n’a besoin de rien d’autre : le PDF dessine chaque système en tracés vectoriels et compose les chiffres dans la Caslon incorporée.
#5 · Ouvrir le chapitre sur un titre abaissé
const opener = {
enabled: true,
minHeight: mm(48),
slot: { elements: [
{ kind: 'text', id: 'kicker', content: '{attr.kicker}', fontFamily: LABEL, fontSize: pt(8.5),
fontWeight: 700, letterSpacing: pt(1.7), textTransform: 'uppercase', color: col('accent'),
align: 'left', placement: { anchor: { to: 'container', edge: 'top-left' },
offset: { x: mm(0), y: mm(12) } } },
{ kind: 'text', id: 'title', content: '{titleText}', fontFamily: 'Libre Caslon Display',
fontSize: pt(34), lineHeight: 1.05, color: col('ink'), align: 'left', overflow: 'wrap',
placement: { anchor: { to: '#kicker', edge: 'below' }, offset: { x: mm(0), y: mm(3) },
size: { width: mm(110), height: 'auto' } } },
{ kind: 'rule', id: 'rule', direction: 'horizontal', thickness: pt(1.5),
color: col('accent'),
placement: { anchor: { to: '#title', edge: 'below' }, offset: { x: mm(0), y: mm(5) },
size: { width: mm(16) } } },
] },
};
L’ouverture tire son surtitre de l’attribut kicker du titre et réserve 48 mm, assez pour le titre et son filet, avec le premier exemple encore en page 1.
La recette complète
// ═══ Postext Cookbook · Nº 163 · Harmony textbook with ABC examples ═════════════
// https://postext.dev/en/cookbook/harmony-textbook-abc-examples
// Code: MIT · Text: original (CC BY 4.0) · Music: Greensleeves (traditional, PD)
// Fonts: Libre Caslon Text & Display, Libre Franklin (SIL OFL 1.1) · 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 = 'harmony-textbook-abc-examples';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: a conservatory green for the accents, warm ink for text and notes
const palette = {
ink: '#1f1c19', // text and notation: a warm near-black
accent: '#2f5d4f', // kickers, rules, Roman numerals in the table
tint: '#edf2ef', // the box of key terms
rule: '#c3cfc9', // hairlines
muted: '#5c6863', // running heads, 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' } })),
// The engine's defaults link to main-color: point it at the accent, never the default blue.
{ id: 'main-color', name: 'accent (defaults)', value: { hex: palette.accent, model: 'hex' } },
];
// #endregion
const TRIM = { width: 180, height: 250 };
const MARGIN = { top: 22, bottom: 24, inner: 22, outer: 33 }; // a 125 mm measure
const LEAD = 14.5; // body leading in pt: the baseline grid
const LABEL = 'Libre Franklin';
// #region answer: one score style for every example in the text
// Each ```abc fence in the chapter is engraved at the width of the text column and cut
// into systems. The style is set once here; the Markdown only holds the notation.
const scoreStyle = {
staffSize: mm(5.5), // a textbook's rastral: examples read at arm's length on a desk
musicFont: 'Bravura', // the traditional engraved look, heavy enough beside Caslon
textFont: 'Libre Caslon Text', // the Roman numerals of `w:` lines, in the text face
spacing: 1.6, // air between the chords: an example reads as a progression, not a cluster
barNumbers: 'system',
systemGap: mm(4),
marginTop: pt(LEAD / 2),
marginBottom: pt(LEAD / 2),
color: col('ink'),
// A long example runs on into the next page between two systems, never leaving one
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
#Prendre Leland pour une page plus légère
Leland, la police de MuseScore, a des hampes plus fines et des têtes de notes plus petites que Bravura ; elle convient à un livre composé dans un caractère de texte léger.
- musicFont: 'Bravura',
+ musicFont: 'Leland',#Écrire une deuxième voix dans un autre format
Le lecteur ABC ne prend qu’une voix. Pour un soprano et une basse sur des portées séparées, écrivez l’exemple en Humdrum ou en MusicXML ; la méthode de conservatoire compose ainsi des chorals à quatre voix.
Erreurs fréquentes
- Écrivez la durée d’un accord à l’intérieur des crochets,
[B2d2g2], ou réglezL:sur la valeur de l’accord : une durée placée après le crochet,[Bdg]2, est lue comme la durée par défaut. - Le lecteur ABC de Verovio donne chaque syllabe d’une ligne
w:à la note suivante et ignore*et_: une lignew:ne peut donc pas sauter de notes. Pour marquer quelques mesures, écrivez les marques comme des chiffrages d’accords au-dessus de la portée, comme le fait l’exemple de Greensleeves. - Un caractère de texte a rarement les signes ♯ et ♭ : écrivez « fa dièse » dans le texte, sinon le navigateur prend le signe dans une police du système.
Crédits
- Recette
- Ignacio Ferro
- Texte
- The chapter on cadences and its examples, written for this recipe · Ignacio Ferro · CC BY 4.0
- Greensleeves, English tune of the sixteenth century, in its common modern form · Traditional · domaine public
- Polices
- Libre Caslon Text (SIL OFL 1.1) · Libre Caslon Display (SIL OFL 1.1) · Libre Franklin (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)


