\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 30 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 } \header { tagline = "" } \relative { \once \override Staff.TimeSignature #'stencil = ##f \override Score.NonMusicalPaperColumn.padding = #2 f'16 c'2 } \addlyrics { Ta -- ta! }
Prince is a HTML-to-PDF-via-CSS converter which offers advanced layout capabilities. Prince excels at formatting text, images and figures into PDF documents. Prince does not support musical notation natively, but will happily read SVG files with musical scores. In this quick guide, you will learn how to embed musical notation in HTML files and generate the necessary SVG files behind the scene. This tutorial requires some knowledge of linux and how to install software on your own machine. With the tools in place, you will be able to generate the PDF version of this document.
The purpose of this guide is to show how small musical snippets can be included in your documents. For example, if you are writing an article about a musician, you may want to include a few bars of music to remind readers of a catchy tune.
Our language of choice for expressing musical notation is Lilypond
. Lilypond is also the name of a computer program that interprets this musical notation and converts it into SVG, which Prince can include. Here is a simple Lilypond example:
\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 170 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 } \header { tagline = "" } \relative { c' d e( f) g2 a2 }
c.ly\relative { c' d e( f) g2 a2 }
When processed by the Lilypond program, the above code is nicely rendered into an SVG file which Prince &ndash and browsers! – can show:
You can find the Lilypond source file in the links on the right side.
Musical notation can be complex, and Lilypond has many advanced features which allows it to generate beautiful musical engravings
. You can learn more about the Lilypond syntax in their documentation.
The small code example above is complete, but it will generate a full sheet and not the small snippets we use in this guide.
In order to create small snippets, one must add some headers:
\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 170 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 } \header { tagline = "" } \relative { c' d e( f) g2 a2 }
cr.ly\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 170 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 } \header { tagline = "" } \relative { c' d e( f) g2 a2 }
The first header declares the version of Lilypond the code is written for. The code in the \paper
section turns off page breaking, then sets the output width to 170 millimeters, and removes indentation and margins around the example. In the \header
section, the default promotional tagline is removed.
One goal of this tutorial is to embed the musical notation inside the HTML code. Having only one file is simpler. However, in order to present the musical notation to Lilypond for processing, it must be extracted from the HTML file. We will use the htmlq
processor for this, and you will need to install htmlq on your own computer to follow this tutorial. (Or, you must find some other way to extract the Lilypond code; copy and paste will also work.)
If you use snap, this command should work:
$ snap install htmlq
Also, we need LilyPond. On a common Linux computer, Lilypond can be installed with:
$ sudo apt-get install lilypond
The third and final tool needed is wget. It's probably already installed on your machine.
To generate the PDF version of the document you are reading, you will first need to download the HTML source file. That's easy:
$ wget https://css4.pub/2024/music/index.html
You should now have a file called index.html
in your directory. (You may want to create a new directory for this experiment.)
The next step is to run Prince:
$ prince --javascript index.html
In the console, Prince will complain about missing SVG files. That's ok. It will also show you the command to generate these SVG files:
htmlq -t .ly#crh < index.html > crh.ly; lilypond --svg crh.ly; htmlq -t .ly#c < index.html > c.ly; lilypond --svg c.ly; htmlq -t .ly#cr < index.html > cr.ly; lilypond --svg cr.ly; htmlq -t .ly#dv < index.html > dv.ly; lilypond --svg dv.ly; prince index.html
It's a bit cryptic, but you will not need to study it. The command is generated by a small script inside the HTML file; the script looks for elements with class=ly
and an id
attribute; this is where we hide the Lilypond code:
<pre class=ly id=dv> \version "2.22.1" ... </pre>
When running the command, htmlq
will extract the Lilypond code and copy it into a separate file. Thereafter, Lilypond will be called to convert the file into SVG. Finally, prince
is called again to process the document now that the SVG files are available. So, Prince is called twice: first to print out a command, and then to generate the final PDF file.
Linux has an elegant way of handling all this in a one-line command:
$ eval "$(prince -j index.html)"
If all goes well, you will now have a file called index.pdf
in your directory.
Here's a catchy tune by Händel, with words added underneath:
\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 170 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 } \header { tagline = "" } << \relative { g'2 e4. f8 g2 c, d8 e f g f4 e4 d1 e8( f) g a g4 g c2 g f4 e d4. c8 c1 } \addlyrics { Deg væ -- re æ -- re Her -- re ov -- er død -- ens makt. E -- vig skal dø -- den væ -- re Kris -- tus un -- der -- lagt. } >>
c.ly<< \relative { g'2 e4. f8 g2 c, d8 e f g f4 e4 d1 e8( f) g a g4 g c2 g f4 e d4. c8 c1 } \addlyrics { Deg væ -- re æ -- re Her -- re ov -- er død -- ens makt. E -- vig skal dø -- den væ -- re Kris -- tus un -- der -- lagt. } >>
When text is introduced, the questions of fonts come up.
The Lilypond program will only find fonts that are installed on your computer. You can make Lilypond use specific font names instead of its default generic font families roman
, sans
, and typewriter
. In this code, all three are replaced with the not-so-suitable Comic Sans MS
:
\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 170 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 #(define fonts (make-pango-font-tree "Comic Sans MS" "Comic Sans MS" "Comic Sans MS" (/ staff-height pt 20))) } \header { tagline = "" } \relative { \time 3/8 \key d \major r8 r8 a'8 a d16( a) fis( d) a'8 a r8 } \addlyrics { auf, prei "- set" die Ta "- ge!" }
b.ly #(define fonts (make-pango-font-tree "Comic Sans MS" "Comic Sans MS" "Comic Sans MS" (/ staff-height pt 20)))
The result can be seen in this excerpt from the Christmas Oratorio:
The font size can also be set to an absolute point size:
\version "2.22.1" \paper { page-breaking = #ly:one-page-breaking paper-width = 170 indent = 0 top-margin = 0 bottom-margin = 0 left-margin = 0 right-margin = 0 #(define fonts (make-pango-font-tree "Comic Sans MS" "Comic Sans MS" "Comic Sans MS" (/ staff-height pt 20))) } \header { tagline = "" } \relative { \time 3/8 \key d \major r8 r8 a'8 a d16( a) fis( d) a'8 a r8 } \addlyrics { \markup \abs-fontsize #20 { auf, prei "- set" die Ta "- ge!" } }
b2.ly\addlyrics { \markup \abs-fontsize #20 { auf, prei "- set" die Ta "- ge!" } }