In short
A chapter of a study of medieval music. Short passages of a 13th-century English round are printed as music in the text, and the notes at the foot of each page record where the old editions disagree, bar by bar.
What you'll build
Chapter 3 of a scholarly study of how English antiquaries read medieval music: five pages at 156 × 234 mm on Sumer is icumen in, the Reading rota, and the editors who scored it between 1776 and 1889. Three passages of the round are engraved in the text in Leipzig at a 5 mm staff, numbered in the bar numbers of W. S. Rockstro's score, and each discussion cites its apparatus at the foot of the page: "b. 40, n. 2 A ] G Hw, Bu". The notes are short and dense in the way an apparatus is, the music sits on the measure of the text, and every reading comes from Rockstro's article in Grove's Dictionary, which the chapter says in its second paragraph.
This recipe answers
- How do I give music examples a critical apparatus of source variants in footnotes?
- How do I do footnotes?
The short answer
// In the Markdown each example is a ```mei fence. A variant is encoded where it stands,
// <app><lem>…</lem><rdg source="#Hw #Bu">…</rdg></app>: the staff shows the lemma, and
// the file keeps the reading for anyone who opens the encoding. The apparatus entry is a
// footnote cited from the paragraph that discusses the bar: `[^b40]: **b. 40, n. 2** A ] G`.
const scoreStyle = {
staffSize: mm(5), // running-text examples: 4.5–5.5 mm
musicFont: 'Leipzig', // lighter than Bravura, close to a 19th-century plate
textFont: 'Crimson Pro', // the underlay in the book's own face
barNumbers: 'system', // the apparatus is keyed by bar: number every system
spacing: 0.95,
systemGap: mm(4),
marginTop: pt(4),
marginBottom: pt(LEAD / 2),
color: col('ink'),
minSystemsAtBreak: 2, // never leave one system of an example alone at a page foot
};
const footnotes = {
placement: 'column', // the foot of the page in one column
numbering: 'chapter',
fontSize: pt(8.5),
lineHeight: pt(10.75),
hangingIndent: em(1.2), // turnover lines align past the number
spaceBetween: pt(2),
separator: { width: 0.2, lineWidth: pt(0.5), color: col('rubric') },
};
MEI examples engraved in the text, their apparatus in footnotes
Ingredients
- Features
- Music notationFootnotesScore styleDesigned openersHeading attributesRunning heads and foliosMirrored marginsHeads by page roleParagraph stylesSemantic colour palettePaper colourWidows, orphans and runtsPDF export
- Type
- Crimson Pro, Cormorant Garamond, Source Sans 3 (SIL OFL 1.1)
- Assets
- None: every picture is drawn in code
Method
#1 · Write each example as MEI, variants included
The settings are the short answer above; the music is in the Markdown, one ```mei fence per example. Where two sources disagree, the measure holds <app> with the adopted reading in <lem> and the other in <rdg source="#Hw #Bu">. The engraver prints the lemma, so bar 40 of Example 3.3 shows the A, and the G of Hawkins and Burney stays in the file for anyone who opens the encoding. Give each fence an alt in the page's language: it is what a screen reader and the tagged PDF read for the score.
#2 · Key the apparatus to the bars the reader sees
barNumbers: 'system' numbers the first bar of every system, and each fence's <measure n="37"> starts the count where the excerpt starts in the edition it follows, so Example 3.3 opens at 37 and a note that says "b. 40" points at a bar the reader can find. The apparatus entry is an ordinary footnote cited from the paragraph that discusses the bar: lemma, closing bracket, variant, sigla in italics. A note cannot be cited from inside a score, so the citation goes on the sentence that names the reading.
#3 · Size the music for running text
A 5 mm staff in Leipzig sits on a 116 mm measure with five or six bars of 3/2 to a system, which keeps the eleven bars of Example 3.3 to two systems. textFont sets the underlay in Crimson Pro, the face of the body, and minSystemsAtBreak: 2 stops a page from ending with one system of an example while the rest goes on. The example label is a third-level heading, so it never stays at the foot of a page without its score.
#4 · Let a page with notes end short
const opener = {
enabled: true,
minHeight: mm(50), // every chapter's text starts on the same grid line
slot: { elements: [
{ kind: 'text', id: 'kicker', content: '{attr.kicker}', ...label, fontSize: pt(8.5),
letterSpacing: pt(1.8), color: col('rubric'), align: 'left',
placement: at('container', 'top-left', 0, 8) },
{ kind: 'text', id: 'title', content: '{titleText}', fontFamily: 'Cormorant Garamond',
italic: true, fontWeight: 500, fontSize: pt(29), lineHeight: 1.05, color: col('ink'),
align: 'left', overflow: 'wrap', // design text ends in an ellipsis by default
placement: { ...at('#kicker', 'below', 0, 3), size: { width: mm(100), height: 'auto' } } },
{ kind: 'rule', id: 'rule', direction: 'horizontal', thickness: pt(1), color: col('rubric'),
placement: { ...at('#title', 'below', 0, 5), size: { width: mm(14) } } },
] },
};
The opener sinks the text 50 mm under a Cormorant italic title. Below it, a page whose next line would bring a long note with it ends a few lines early, and balancing: { maxLinesPerHeading: 1 } keeps column balancing from pushing that gap above the next section heading, where it would read as a break in the argument.
#5 · Put the book on the verso and the chapter on the recto
const head = (id, content, parity, edge, x, extra = {}) => ({
kind: 'text', id, content, parity, pages: 'body', // never on the opener
...label, fontSize: pt(7.5), letterSpacing: pt(1.3), color: col('muted'),
placement: at('page', edge, x, 13), ...extra,
});
const folio = { color: col('rubric'), fontWeight: 700 };
const header = { elements: [
head('verso-folio', '{pageNumber}', 'even', 'top-left', MARGIN.outer,
{ ...folio, align: 'left' }),
head('verso-title', '{title}', 'even', 'top-left', MARGIN.outer + 8, { align: 'left' }),
head('recto-title', '{chapterTitle}', 'odd', 'top-right', -(MARGIN.outer + 8),
{ align: 'right', overflow: 'ellipsis' }),
head('recto-folio', '{pageNumber}', 'odd', 'top-right', -MARGIN.outer,
{ ...folio, align: 'right' }),
] };
// The opener carries a drop folio instead, centred under the text block.
const footer = { elements: [{ ...head('drop-folio', '{pageNumber}', 'all', 'bottom', 0,
{ ...folio, align: 'center', placement: at('page', 'bottom', 0, -11) }), pages: 'opener' }] };
Folios in the rubric red on the outer edge, the book on the verso and the chapter on the recto; pages: 'body' keeps them off the opener, which takes a centred drop folio.
The whole recipe
// ═══ Postext Cookbook · Nº 165 · MEI music examples with a critical apparatus ═════
// https://postext.dev/en/cookbook/musicology-mei-apparatus
// Code: MIT · Text: original (CC BY 4.0) · Music: Sumer is icumen in, after Rockstro (PD)
// Fonts: Crimson Pro, Cormorant Garamond, Source Sans 3 (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 = 'musicology-mei-apparatus';
// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: a rubric red for kickers, labels and the notes' rule; ink on cream
const palette = {
ink: '#211d1a', // text and notation: a warm near-black
rubric: '#8c2f1f', // the one accent, the red of the manuscript's rubrics
muted: '#6c645b', // running heads, colophon
rule: '#cbbfae', // hairlines
paper: '#fcfaf6',
};
// col(id): a colour linked to its palette entry, with the entry's hex beside the id.
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.rubric, model: 'hex' } },
];
// #endregion
const MARGIN = { top: 22, bottom: 22, inner: 19, outer: 21 }; // 156 × 234 mm, mirrored
const LEAD = 14.5; // body leading in pt: the baseline grid
const at = (to, edge, x = 0, y = 0) => ({ anchor: { to, edge }, offset: { x: mm(x), y: mm(y) } });
const label = { fontFamily: 'Source Sans 3', fontWeight: 600, textTransform: 'uppercase' };
// #region answer: MEI examples engraved in the text, their apparatus in footnotes
// In the Markdown each example is a ```mei fence. A variant is encoded where it stands,
// <app><lem>…</lem><rdg source="#Hw #Bu">…</rdg></app>: the staff shows the lemma, and
// the file keeps the reading for anyone who opens the encoding. The apparatus entry is a
// footnote cited from the paragraph that discusses the bar: `[^b40]: **b. 40, n. 2** A ] G`.
const scoreStyle = {
staffSize: mm(5), // running-text examples: 4.5–5.5 mm
musicFont: 'Leipzig', // lighter than Bravura, close to a 19th-century plate
textFont: 'Crimson Pro', // the underlay in the book's own face
barNumbers: 'system', // the apparatus is keyed by bar: number every system
spacing: 0.95,
systemGap: mm(4),
marginTop: pt(4),
marginBottom: pt(LEAD / 2),
The composed script.js runs as it is: paste it into any page’s module script, or open the recipe on CodePen. Recipe folder on GitHub ↗ (opens in a new tab)
Variations
#Print every bar number
An apparatus with many entries per system is easier to follow with a number on each bar.
- barNumbers: 'system', // the apparatus is keyed by bar: number every system
+ barNumbers: 'every',#Set the examples in Bravura
Bravura's heavier noteheads match a plate-engraved house style.
- musicFont: 'Leipzig', // lighter than Bravura, close to a 19th-century plate
+ musicFont: 'Bravura',Pitfalls
- MEI 5 writes the key signature as
keysig="1f"onscoreDeforstaffDef. The MEI 4 attributekey.sigis ignored without a message, and the flat disappears. - Give every
staffDefitslines="5": without it the notes and clefs are engraved on no staff at all. - The engraver prints the
<lem>of an<app>, not the<rdg>. A variant the reader must see on the page belongs in the apparatus note or in a second example.
Credits
- Recipe
- Ignacio Ferro
- Text
- The chapter text and the apparatus notes, in English and Spanish · Ignacio Ferro · CC BY 4.0
- Sumer is icumen in (13th century), the music examples transcribed from W. S. Rockstro's score and the readings his article reports, in A Dictionary of Music and Musicians, ed. George Grove, vol. 3, pp. 765–768, and vol. 4, pp. 1–3 (Macmillan, 1900 printing), as transcribed on Wikisource · Anonymous; William Smyth Rockstro · public domain
- The Latin rubric of Harley MS 978, f. 11v, and the folio, as quoted in the Wikipedia article (fact check) · Wikipedia contributors · CC BY-SA 4.0
- Fonts
- Crimson Pro (SIL OFL 1.1) · Cormorant Garamond (SIL OFL 1.1) · Source Sans 3 (SIL OFL 1.1)
Edit this write-up ↗ (opens in a new tab)Recipe folder on GitHub ↗ (opens in a new tab)


