本文へスキップ
レシピ番号164

レシピ集 · 第9章 · 完成した出版物

旋律と歌詞とコードを載せた歌集

各曲はABCのブロックです。旋律、譜表の上のコード名、音符の下の1番の歌詞を、1つの楽譜スタイルで段の幅に合わせて浄書します。

このページの内容
出力
Canvas · PDF
レベル
中級
Postext
Postext 1.54.0で検証済み
1.54.0以上が必要 · postext-pdf ≥ 1.54.0
ライセンス
2026年10月22日更新
コードMIT · 本文CC BY 4.0

2〜3ページ(全6ページ)

  • 英語の見本:日本語版はまだありません
  • 仕上がり148 × 210 mm
  • 1段
  • Spectral 10.3/14
  • Fraunces
  • Spectral SC
  • 6ページ
  • レベル
  • Postext 1.54.0
  • 組版時間300 ms
  • コード164行

かんたんな説明

食卓を囲んで歌うための小さな歌集です。各曲はABCという記譜法でただの文字として書き、Postextが五線、音符、ギターのコード、音符の下の歌詞を描きます。残りの節は2段に組んで続けます。

できあがり

『Songs for the Long Table』は、A5判の小さな歌集です。茜色の扉、目次を添えた歌い手への前書き、3曲の歌、各曲の出どころについての覚え書きを収めます。どの曲も、茜色の大きな番号、Frauncesの曲名、スモールキャピタルのクレジット行で始まります。その下にLelandで5.5 mmの譜表に旋律を組み、小節の上にギターのコードを、音符の下に本書の本文書体Spectralで1番の歌詞を置きます。残りの節は2段に並ぶので、歌い手は最後の小節からそのまま下へ読み進められます。『Amazing Grace』は行が長く、段の中では折り返してしまうため、節を1つずつ縦に重ね、中央揃えにします。スペイン語版は誕生日の歌集で、短めの3曲を1ページに2曲ずつ組みます。

このレシピが答える質問

  • 旋律と音符の下の歌詞、コードネームの付いた歌集を組むには?

手短な答え

script.js · 33〜50行コード全体で見る
// 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".

材料

種類
Spectral, Spectral SC, Fraunces (SIL OFL 1.1)
素材
なし:画像はすべてコードで描画

作り方

#1 · 歌を書き、楽譜スタイルは一度だけ決める

楽譜スタイルは前出の手短な答えです。Markdownでは、各曲が```abcのブロックになります。ヘッダー行で拍子、音符の長さ、調を決めます。二重引用符で囲んだコード名("D7"A)は、すぐ後ろの音符の上に刷られます。音楽の下のw:行は音符ごとに1音節を置き、音節はハイフンで区切ります。ヴァースとコーラスのある曲は音楽の行を2つにし、それぞれにw:行を付けます。譜表の大きさ、音楽フォント、歌詞の書体、小節番号、譜の段と段の間隔はscoreStyleで決まるので、3曲の見た目がそろい、ブロックには音楽だけが残ります。

#2 · 番号とクレジットの下で各曲を始める

script.js · 66〜81行コード全体で見る
// # 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 } };

曲はcredit属性を持つ第1レベルの見出しで、その見出しのデザインが番号、曲名、クレジット行を組みます。minHeightでどの曲の見出しも高さ21 mmにそろえるので、どのページでも譜表が同じ深さから始まります。曲は追い込みで続き、各曲名の上に3行分の空きを取ります。楽譜は2段目より前では決して分割されません(minSystemsAtBreak: 2)。英語版の曲は1ページに1曲ずつ収まり、スペイン語版の短い曲は2曲で1ページを分け合います。

#3 · 残りの節を2段に組む

script.js · 54〜62行コード全体で見る
// :::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) };

各節は:::verseブロックなので、行は詩人が改行したところで改行され、2行目と4行目が1 em字下げされます。:::columns{count=2 gap=4mm}のグループが、それらを9.4 ptで横に並べます。先に文字数を数えてください。バーンズ(Burns)の行は55 mmの段に収まりますが、ニュートン(Newton)のロングメーターは収まりません。そこで『Amazing Grace』は中央揃えの:::verseブロック1つのままにし、空行で節を分けます。

#4 · 柱とノンブルは控えめに

script.js · 119〜131行コード全体で見る
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),
] };

柱は曲が載るすべてのページに入り、偶数ページに書名、奇数ページに曲名を置きます。ノンブルは曲番号と同じ茜色です。扉と歌い手への前書きは、それぞれの見出しスタイルで空のheaderを指定して柱を消します。

レシピの全体

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

組み立てたscript.jsはそのまま動きます。任意のページのモジュールスクリプトに貼り付けるか、レシピをCodePenで開いてください。 GitHub上のレシピのフォルダー ↗ (新しいタブで開きます)

アレンジ

#Bravuraで浄書する

Bravuraは符頭が太く、彫版で刷った楽譜の趣があります。濃いめの本文書体で組む讃美歌集に向きます。

-  musicFont: 'Leland', // lighter noteheads than Bravura, close to Spectral's colour
+  musicFont: 'Bravura',

#小節に番号を振る

合唱団は小節番号を頼りに練習します。譜の各段の頭に1つずつ刷ります。

-  barNumbers: 'none', // a table of singers counts verses, not bars
+  barNumbers: 'system',

よくあるつまずき

つまずき

見出しスタイルはその階層の改ページを受け継ぐ

headingStylesの項目は、指定しなかったフィールドをすべて見出しの階層から受け継ぎ、breakBeforeも例外ではありません。:::pagebreakのあとのH1に付けた目次や奥付のスタイルはparity 'odd'を受け継ぎ、白ページの後ろに置かれます。こうしたスタイルにはbreakBefore: { enabled: false }を指定してください。 見出しスタイル →

  • VerovioのABCリーダーは、w:行の保持記号_と*を無視します。どの音符も次の音節を取ります。スラーの2つ目の音符の下には、ノーブレークスペース(U+00A0)を1つの音節として書いてください。何も刷られません。タイでつないだ音符は音節を取りません。
  • ~は2つの音節を1つの音符の下にまとめます(de~a-trás)が、浄書エンジンはそれを連結弧ではなく普通のスペースで刷ります。
  • コード名には、できるだけ♭や♯を使わないでください。たいていの本文書体にはこれらの記号がなく、ページはシステムフォントに切り替わります。コードが幹音だけになる調(G、C、D7、Em)を選ぶか、本文で「変ロ」と書きます。

クレジット

レシピ
Ignacio Ferro
本文
フォント
Spectral (SIL OFL 1.1) · Spectral SC (SIL OFL 1.1) · Fraunces (SIL OFL 1.1)
SandboxPDF