Changelog
1.1.2
Patch Changes
- Fixes attempts to import a missing
@astrojs/markdown-remarkpackage even when Remark is unused.
1.1.1
Patch Changes
- Fixes a type error on
LilypondScorewheresourceNamewas being treated as a required prop.
1.1.0
Minor Changes
-
Adds an
includePathsconfig option to extend\includeresolution with extra directories, in addition to each score’s own directory.To enable, pass an array of directories to
includePathsin the integration config:astro.config.mjs lilypond({includePaths: ["./src/snippets"],});This will ensure that LilyPond has access to any styles, layouts, and helper definitions which are defined separately from the score itself.
1.0.0
Major Changes
-
Announcing Astro Lilypond 1.0!
The
astro-lilypondpackage is now stable. Use it to help write and render music notation on your Astro site.To install it in an existing Astro project:
Terminal window pnpm astro add astro-lilypondOr follow the getting started guide.
Features:
- Render text to music notation via Markdown or with an Astro component.
- Works with
remarkandsatteriMarkdown processors out-of-the-box. - Generates automatic alt text from the score’s title and composer. (Or supply your own.)
- Includes a
lilypondLoader()for creating an Astro content collection from a folder of.lyfiles. Automatically extracts metadata. - Works with all LilyPond syntax. Check out the examples to see what’s possible!
- 100% unit test coverage and full end-to-end tests.
View all docs at lilypond.ky.fyi.
BREAKING:
-
render()has been renamed togetScore(), and its typesRenderOptions/RenderResulttoGetScoreOptions/GetScoreResult. To update, replacerenderimports withgetScore:---import { render } from "astro-lilypond";import { getScore } from "astro-lilypond";import bachInvention from "./bach-invention.ly";const { Score, meta, raw, pdf } = await render(bachInvention);const { Score, meta, raw, pdf } = await getScore(bachInvention);--- -
renderAll()has been removed. UsePromise.allwithgetScoreinstead:---import { getCollection } from "astro:content";import { renderAll } from "astro-lilypond";import { getScore } from "astro-lilypond";const scores = await getCollection("scores");const rendered = await renderAll(scores.map((s) => s.data));const rendered = await Promise.all(scores.map((s) => getScore(s.data)));--- -
pageCount: numberis replaced bypages: LilypondPage[]ongetScore()’s result. Usepages.lengthfor a count:---const { Score, pageCount } = await render(bachInvention);const { Score, pages } = await getScore(bachInvention);---<p>{pageCount} pages</p><p>{pages.length} pages</p>The new
pagesobject containssrc/width/heightand can be used to build your own markup instead of using the built-inScorecomponent:---const { pages } = await getScore(bachInvention);---<div class="gallery">{pages.map((page) => <img src={page.src} width={page.width} height={page.height} />)}</div> -
The
formatconfig has been relocated beneathdefaults:lilypond({format: "png",defaults: {format: "png",},})Previously,
formatonly set the default for Markdown fences;.ly/.ilyimports andlilypondLoader()entries always defaulted to"svg".defaults.formatnow applies everywhere.
0.17.1
Patch Changes
- Fix overzealous CSS reset on error blocks rendered in dev mode.
0.17.0
Minor Changes
-
Syntax errors in LilyPond code now render an inline error message during
astro devinstead of crashing the entire page. The message includes logging from LilyPond indicating where the syntax error was detected.astro buildis unaffected, and will still fail loudly if LilyPond syntax errors are present. -
Remove the
defaultsoption fromlilypondLoader(). The content loader now always uses the integration’s owndefaults, matching.lyfile imports and Markdown fences. -
Improve logging from astro-lilypond. Logs are now emitted using Astro’s logger, and LilyPond logs are less verbose, only emitting warnings and above.
Patch Changes
- Declare
engines.node: ">=22.12.0", matching the Astro 7’s requirement.
0.16.2
Patch Changes
- Removes the rehype plugin. The
unifiedMarkdown processor always registers and usesremarkfirst, so there should not be any user-facing impact from this. - Fixes an issue where fenced LilyPond code blocks inside
.mdxwould render as text instead of images.
0.16.1
Patch Changes
- Content collections from
lilypondLoader()will now return correct TypeScript types forentry.datainstead of returning data asany.
0.16.0
Minor Changes
-
Add a
<Score>component for the common case of just displaying a score, without needing to callrender()from frontmatter:---import { Score } from "astro-lilypond";import bachInvention from "./bach-invention.ly";---<Score content={bachInvention} />If you’re only using
render()to get aScoreto display (notpageCount,meta,raw, orpdf), you can drop the frontmatter call entirely:---import { render } from "astro-lilypond";import { Score } from "astro-lilypond";import bachInvention from "./bach-invention.ly";const { Score } = await render(bachInvention, { crop: true });---<Score /><Score content={bachInvention} crop />render()itself is unchanged and still the way to getpageCount,meta,raw, or apdflink alongside the image.This also plays a similar role to the pre-v0.15
<LilyPond>component: both take your imported.lyfile directly via acontentprop, and both acceptpageLimit,class,style, andaltprops.<Score>additionally acceptsformatandcrop, which previously requiredrender()’s options:---import LilyPond from "astro-lilypond/component";import { Score } from "astro-lilypond";import bachInvention from "./bach-invention.ly";---<LilyPond content={bachInvention} /><Score content={bachInvention} />
Patch Changes
- Removes the
defaults.cropconfig setting. All Markdown blocks are now cropped by default. Components can customize cropping per-instance.
0.15.0
Minor Changes
-
BREAKING: Scores are now parsed using a
render()function instead of being passed directly to a<LilyPond>component. If you were previously importing.lyfiles and passing them to the<LilyPond>component, update your code to instead pass the.lyfile to arender()function inside of the frontmatter of an.astrofile:---import LilyPond from "astro-lilypond/component";import { render } from "astro-lilypond";import bachInvention from "./bach-invention.ly";const { Score } = await render(bachInvention);---<LilyPond content={bachInvention} /><Score />The
render()function takes your.lyfile and returns aScorecomponent which you can render on the page.If you were using the
?cropor?nocropquery params in imports, those are now exposed as config options insiderender():---import { render } from "astro-lilypond";import bachInvention from "./bach-invention.ly?crop";import bachInvention from "./bach-invention.ly";const { Score } = await render(bachInvention, { crop: true });---<LilyPond content={bachInvention} /><Score />BREAKING:
lilypondLoader()collection entries no longer spread\headerfields (title,composer,opus, etc.) directly ontoentry.data. They now live underentry.data.meta:<h3>{entry.data.title}</h3><h3>{entry.data.meta.title}</h3>Additionally, you can now return
pdffiles from scores which can be exposed as download links. Set{ pdf: true }in therender()config, then usepdf.srcfrom the result:---import { render } from "astro-lilypond";import bachInvention from "./bach-invention.ly";const { Score, pdf } = await render(bachInvention, { pdf: true });---<Score /><a href={pdf.src} download>Download PDF</a>render()also returnspageCountandraw(the exact LilyPond source text).A new
renderAll()function renders many scores at once; this is helpful forgetCollection()results.<Score>accepts the same props as<LilyPond>did:pageLimit,class,style, andaltprops. Once you’ve set up yourrenderfunction, you should be able to swap out<LilyPond content={...} />for<Score />.
0.14.0
Minor Changes
-
Add automatic LilyPond installation via a new
autoInstalloption (on by default). When nolilypondbinary is found onPATH, a matching prebuilt release is downloaded and cached. Alilypondalready onPATHis always used instead.If you were manually installing
lilypondin CI, that logic can be removed.If you would prefer to continue managing manual installation of
lilypond, setautoInstall: falsein your integration config.
0.13.0
Minor Changes
-
BREAKING: The
outputDiroption has been removed from bothlilypond()andlilypondLoader().astro-lilypondnow relies onastro-emit-assetfor asset hashing, writing, and pruning. Rendered scores are now cached and served through Astro’s own asset pipeline instead of being written to a directory underpublicDir.If you had previously set
outputDirin your integration config or collection loader, remove it.Likewise, if you had previously configured
.gitattributesor.gitignoreto ignore the_lilyponddirectory, that config can be safely removed.If you were committing files in
outputDir(e.g.public/_lilypond) to your repo, you can delete that directory.
0.12.0
Minor Changes
- Add a
pageLimitprop to<LilyPond>to limit rendering to the firstnpages of a multi-page score.
0.11.1
Patch Changes
- Remove source maps from the published package, fixing Vite’s “missing source file” warning.
0.11.0
Minor Changes
-
Add
lilypondLoader()for exposing a folder of.lyfiles as an Astro content collection, with\headermetadata (title,composer,opus, etc.) parsed onto each entry.src/content.config.ts import { defineCollection } from "astro:content";import { lilypondLoader } from "astro-lilypond/loader";export const collections = {scores: defineCollection({loader: lilypondLoader({ base: "./src/content/scores" }),}),};---import { getCollection } from "astro:content";import LilyPond from "astro-lilypond/component";const scores = await getCollection("scores");---<ul>{scores.map((score) => (<li><h3>{score.data.title}</h3><LilyPond content={score.data} /></li>))}</ul>
0.10.1
Patch Changes
- Fix
Cannot find moduleTypeScript errors on.ly/.lilypond/.ilyimports using the?cropor?nocropquery suffix.
0.10.0
Minor Changes
-
BREAKING: Add a new
configoption fordefaults.cropScale. which allows modifying the rendered dimensions of cropped<img>tags to compensate for the fact that LilyPond renders size units in points/mm, which, when translated to pixels, can appear too small.cropScaleis set to1.5by default. As a consequence, this version will render cropped images larger than before.To maintain the previous sizing of cropped images, update your integration config:
astro.config.mjs import { defineConfig } from 'astro/config';import lilypond from 'astro-lilypond';export default defineConfig({integrations: [lilypond()]integrations: [lilypond({ defaults: { cropScale: 1 } })]});
Patch Changes
- Output
widthandheightattributes on all<img>tags to prevent layout shift.
0.9.0
Minor Changes
-
Add alt text support for rendered LilyPond images.
- Alt text is automatically derived from
title/composerfields in a score’s\headerblock, composed as"{title}, by {composer}"(or just the title, or"Sheet music by {composer}", or empty when neither is present). - Override the automatically-derived alt text with
alt="..."in a fenced code block’s meta string (```lilypond alt="..."), or the<LilyPond>component’s newaltprop. - Multi-page scores wrap their pages in an
<ol>, so every page gets the same alt text, leaving it to screen readers already to announce list position on their own.
- Alt text is automatically derived from
0.8.0
Minor Changes
-
BREAKING: Rendered output no longer includes
class="lilypond". Images are now marked with adata-lilypond-imageattribute.To upgrade, update any CSS selectors targeting the old classes:
.lilypond {[data-lilypond-image] {background-color: white;}In addition, you can now target multi-page groups with
data-lilypond-group. -
BREAKING:
<LilyPond>.lyimports no longer crop scores by default; they now render every page.defaults.cropnow acceptstrue | false | "markdown-only"(previouslyboolean) and defaults to"markdown-only"(previouslytrue):"markdown-only"(new default): crop Markdown only;<LilyPond>imports render full, uncropped pages.true(old default): crop everywherefalse: never crop.
A
.lyimport can also override the default per-instance by appending?cropor?nocropto the import path.To keep the old cropped-everywhere behavior:
lilypond({defaults: {crop: true,}})If you don’t use
<LilyPond>component imports, or already setdefaults.cropexplicitly, no change is needed. Multi-page output renders as an<ol>ordered list of images.
0.7.0
Minor Changes
-
BREAKING: The config options for
crop,resolution, andversionhave been moved inside of a newdefaultsobject in the config. This change is meant to help clarify and organize settings which apply by default to each score when rendered, but can be overridden by the score itself as-needed.To upgrade, relocate
crop,resolution, andversionoptions inside ofdefaults:astro.config.mjs export default defineConfig({integrations: [lilypond({crop: true,resolution: 300,version: "2.26.0"defaults: {crop: true,resolution: 300,version: "2.26.0"}}),],});If you have not configured
crop,resolution, orversionin your integration config, no change is needed.
0.6.0
Minor Changes
-
Rendered scores are now written to image files and referenced by URL, instead of being embedded inline as base64 data. This enables a few things:
- Browser-native caching of image assets
- Faster rebuilds since unchanged scores can be skipped
Images are written to a new
outputDirconfig option (which defaults to_lilypond/), output inside Astro’spublicDir(which defaults topublic). You can change theoutpurDirvia the config in the integration:astro.config.mjs lilypond({outputDir: "scores",});Compiled images are regenerated automatically and use content-addressable hashes, meaning that filenames will not change if the content has not changed. You can safely commit generated files to your repository, if you want.
Comitting generated files will make rebuilds and startup faster, since LilyPond does not have to regenerate files from scratch. However, it will increase the size of your repository, which can pose issues if you have many scores, or if you use use
pngoutput with highresolution.If you would prefer that generated scores not show up in your git repository or history, update
.gitignore:# ignore generated LilyPond scorespublic/_lilypond
Patch Changes
- Fixed rendered scores sometimes failing to load in
astro devafter editing a.lyfile or Markdown score, requiring a restart to recover. Dev-mode assets are now written to the same location asastro build, and edited scores no longer leave old versions behind inpublicDir.
0.5.2
Patch Changes
lilypondinvocations now time out after 60 seconds instead of potentially stalling the build indefinitely.
0.5.1
Patch Changes
- Remove unnecessary invocation queue from render pipeline
0.5.0
Minor Changes
-
Update rendering to use
<img>tags for all content, including.svg. Previously, svg scores were inlined in the page. However, thecairo-based backend renderer makes heavy use of SVG’s<use>element. When inlined on the page, these<use>tags can conflict with one another across scores, corrupting the display of notation. To avoid this, SVG elements are now rendered within an<img>tag. This has the benefit of reducing the number of HTML nodes on the page, but the drawback of no longer being able to inheritcurrentColorfor noteheads. Given that the desire for inverted staff paper is unusual (and for many people, likely undesirable), this feels like an acceptable tradeoff.To prevent scores from displaying as black-on-black when in dark mode, add global styles to
.lilypond:.lilypond {background-color: white;}
Patch Changes
- Emit source names to build log when available for easier debugging
0.4.0
Minor Changes
-
BREAKING: The integration has changed how
resolutionis set in order to mirror the API shape of LilyPond’s command line tools.Previously, resolution was set by passing an object with
type: "png"toformat:lilypond({format: {type: "png",resolution: 300,},});Now, resolution is its own config entry, separate from
format:lilypond({format: "png",resolution: 300,});Note that
resolutionstill only applies when format is set topng.
Patch Changes
-
Allow LilyPond to emit text during builds for better insight into warnings and errors from
.lycompilation. -
Use LilyPond’s
cairobackend renderer instead of the defaultpsrenderer. From LilyPond v2.26.0’s major changes:Instead of generating PostScript or SVG output by itself, LilyPond can now use the Cairo library to produce its output. This is referred to as the ‘Cairo backend’, and can be turned on using the -dbackend=cairo command-line option. This works for all output formats (PDF, SVG, PNG, PostScript), and brings speed and rendering fidelity improvements in SVG output in particular. However, keep in mind that this backend does not yet implement all features of the default backends. Among the features not currently supported are PDF outlines, the -dembed-source-code option for PDF, and the output-attributes property for SVG.
0.3.4
Patch Changes
-
Support
\includein LilyPond files to allow importing and reusing snippets from other files:\version "2.25.28"\include "example-header.ily"Add an examples page to the docs which mirrors the content from https://lilypond.org/examples.html.
0.3.3
Patch Changes
- Behavior change: loudly fail the build when attempting to process invalid LilyPond markup. Previously, the build would succeed, but an error message would be emitted to HTML, which could CI builds which pass but web pages which are broken on view. Prefer failing on error instead.
- Fix a broken import from src/utils that was causing
component imports to fail.
0.3.2
Patch Changes
- Automatically inject type definitions to allow importing
.ly,.ily, and.lilypondfiles without manually editingenv.d.ts.
0.3.1
Patch Changes
- Support the
ilyextension for LilyPond files, in addition to the existinglilypondandlymarkers.
0.3.0
Minor Changes
-
Enable setting global and per-component ‘crop’ config.
Set to
falsefor full-page scores where tight cropping is undesirable:---import LilyPond from 'astro-lilypond/component';import excerpt from './scores/excerpt.ly';import fullPage from './scores/full-page.ly';---<LilyPond content={excerpt} /><LilyPond content={fullPage} crop={false} />Or change the default global crop:
astro.config.mjs import { defineConfig } from "astro/config";import lilypond from "astro-lilypond";export default defineConfig({integrations: [lilypond({crop: false,}),],});
0.2.0
Minor Changes
-
Add a
component to allow rendering scores outside of Markdown. ---import LilyPond from 'astro-lilypond/component';import prelude from './scores/prelude.ly';---<LilyPond content={prelude} />
0.1.0
Minor Changes
-
Initial release! Render LilyPond music notation to inline SVG (or PNG) at build time in Astro sites.
Prerequisites
The LilyPond binary must be installed and available on
PATHat build time. The integration renders notation during the Astro build — the binary is not needed at runtime.Installation
Terminal window pnpm add astro-lilypondAdd the integration to your
astro.config.mjs:import { defineConfig } from "astro/config";import lilypond from "astro-lilypond";export default defineConfig({integrations: [lilypond({ version: "2.24.0" })],});Then use fenced code blocks in your Markdown:
```lilypondtext\score { \relative { c' d e f g } }```See the docs for configuration options and live examples.