npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

remark-music-plugins

v0.4.0

Published

remark plugins to insert music notation and guitar fretboard chart in markdown files

Downloads

1,145

Readme

remark music plugins

Remark plugins to insert music notation and guitar fretboard chart in markdown files

Markdown Extensions

LilyPond Integration

The LilyPond extension allows you to embed musical notation directly in your markdown:

```lilypond
\version "2.20.0"

{
  \clef treble
  \time 4/4
  \key c \major

  c'4 d'4 e'4 f'4 |
  g'4 a'4 b'4 c''2
}
```

The plugin will:

  • Detect fenced code blocks with the lilypond language identifier
  • Compile the LilyPond code to SVG using the LilyPond CLI
  • Embed the resulting SVG as inline images in your output

Guitar Fretboard Charts

The svguitar extension uses the svguitar library and Text Guitar Chart to render guitar fretboard diagrams:

```guitar-charts
  A min
  ######
  oo   o
  ------
  ||||o|
  ||o*||
  ||||||

  D
  ######
  xoo
  ------
  ||||||
  |||o|o
  ||||*|
```

Installation

Prerequisites

  • Node.js (version 16 or higher)
  • LilyPond (for musical notation rendering)
  • Google Chrome or Chromium (for guitar chord rendering)

To install LilyPond:

  • macOS: brew install lilypond
  • Ubuntu/Debian: apt install lilypond
  • Windows: Download from lilypond.org

For guitar chord rendering, the plugin uses Puppeteer which will automatically download a suitable version of Chromium. No additional installation is required.

Usage

Basic Usage

import { remark } from "remark";
import remarkHtml from "remark-html";
import remarkLilypond from "./plugins/remark-lilypond/index.js";
import remarkGuitarChart from "./plugins/remark-guitar-chart/index.js";

const processor = remark()
  .use(remarkLilypond)
  .use(remarkGuitarChart)
  .use(remarkHtml, { sanitize: false }); // Required: Allow raw HTML/SVG for musical notation

const result = await processor.process(markdownContent);
console.log(result.toString());

Important: The sanitize: false option is required for the SVG musical notation to display. For production use with untrusted content, consider using remark-rehype with rehype-raw instead for better security.

Plugin Options

LilyPond Plugin Options

const processor = remark().use(remarkLilypond, {
  binaryPath: "lilypond", // Path to LilyPond executable
  errorInline: false, // Show errors inline vs console
  skipOnMissing: false, // Skip processing if LilyPond not found
  compact: true, // Remove attribution and crop whitespace (default: true)
});

GuitarChart Plugin Options

const processor = remark().use(remarkGuitarChart, {
  errorInline: false, // Show errors inline vs console
  skipOnMissing: false, // Skip processing if Puppeteer fails to launch
  puppeteerOptions: {
    // Options passed to puppeteer.launch()
    headless: true,
    args: ["--no-sandbox", "--disable-setuid-sandbox"],
  },
});

Using the Markdown Renderer

The package includes a convenient renderer() function that processes markdown files and generates complete HTML output with embedded styles:

import renderer from "./markdownRenderer/index.js";

// Process a markdown file and generate HTML
await renderer("input.md", "output.html");

Features:

  • Automatically applies both LilyPond and GuitarChart plugins
  • Generates complete HTML document with embedded CSS styles
  • Includes both screen and print stylesheets
  • Handles errors gracefully with helpful error messages
  • Automatically cleans up browser resources

Default Configuration:

The renderer uses these plugin settings by default:

  • errorInline: true - Shows errors inline in the generated HTML
  • skipOnMissing: true - Continues processing even if LilyPond or Puppeteer are unavailable
  • sanitize: false - Allows raw SVG/HTML output (required for musical notation)

Example:

import renderer from "./markdownRenderer/index.js";

// Convert markdown with musical notation to HTML
await renderer("./songs/my-song.md", "./output/my-song.html");

The generated HTML file will include all rendered musical notation and guitar charts, with styling optimized for both screen display and printing.

Command Line Tool

The package includes a CLI tool that processes markdown from stdin and outputs HTML to stdout:

# Process a markdown file
markdown-music-renderer < input.md > output.html

# Or pipe from another command
cat songs/my-song.md | markdown-music-renderer > my-song.html

# Using with node (before installing globally)
node cli.js < input.md > output.html

Features:

  • Reads markdown from stdin
  • Writes complete HTML with embedded styles to stdout
  • Includes both LilyPond and GuitarChart processing
  • Error messages go to stderr, keeping stdout clean
  • Same configuration as markdownRenderer() (errorInline: true, skipOnMissing: true)

Installation:

After installing the package globally, the markdown-music-renderer command will be available:

npm install -g remark-music-plugins
markdown-music-renderer < input.md > output.html

Or use it locally in your project:

npm install remark-music-plugins
npx markdown-music-renderer < input.md > output.html

Running the Demo

Try the included demo to see the plugin in action:

node demo/demo.js

This will process demo/example.md and generate demo/output.html with rendered musical notation and guitar chord diagrams.

Development

Scripts

  • npm test - Run tests using Node.js test runner
  • npm run format - Format code using Prettier (no semicolons)
  • npm run types - Generate TypeScript definitions from JSDoc comments

Contributing

  1. Write comprehensive JSDoc comments with TypeScript type annotations
  2. Add tests for new functionality using the Node.js test runner
  3. Format code using Prettier (no semicolons)
  4. Ensure all tests pass before submitting

Troubleshooting

LilyPond Not Found Error

If you see errors like lilypond: not found or LilyPond executable not found, LilyPond is not installed or not in your system PATH.

Solutions:

  1. Install LilyPond:

    • macOS: brew install lilypond
    • Ubuntu/Debian: sudo apt install lilypond
    • Windows: Download from lilypond.org
  2. Verify Installation:

    lilypond --version
  3. Specify Custom Path:

    const processor = remark().use(remarkLilypond, {
      binaryPath: "/usr/local/bin/lilypond", // Custom path
    });
  4. Skip Missing LilyPond:

    const processor = remark().use(remarkLilypond, {
      skipOnMissing: true, // Skip blocks if LilyPond not available
    });

Compilation Errors

LilyPond compilation errors are usually due to invalid syntax. Common issues:

  • Missing version declaration: Add \\version "2.20.0" at the top
  • Unmatched braces: Ensure all { have matching }
  • Invalid note names: Use proper LilyPond syntax

Set errorInline: true to see errors in the generated HTML instead of just the console.

SVG Output Control

The plugin generates compact, clean SVG output by default:

  • Compact mode (compact: true, default): Removes attribution text and crops excessive whitespace
  • Full mode (compact: false): Preserves original LilyPond output including attribution

Compact mode automatically:

  • Removes "Music engraving by LilyPond" attribution text
  • Crops whitespace to focus on musical content
  • Significantly reduces SVG file size

To disable compact mode:

const processor = remark().use(remarkLilypond, {
  compact: false, // Keep full LilyPond output
});

GuitarChart Chord Data Format

The GuitarChart plugin expects uses the syntax described here

HTML Sanitization

The plugin generates raw SVG content that needs to pass through HTML processing:

Quick Fix (for trusted content):

.use(remarkHtml, { sanitize: false })

Recommended for Production (more secure):

import { remark } from "remark";
import remarkRehype from "remark-rehype";
import rehypeRaw from "rehype-raw";
import rehypeStringify from "rehype-stringify";

const processor = remark()
  .use(remarkLilypond)
  .use(remarkGuitarChart)
  .use(remarkRehype, { allowDangerousHtml: true })
  .use(rehypeRaw)
  .use(rehypeStringify);

TypeScript Usage

Full TypeScript definitions are included. You can import the plugins and option types:

import { remark } from "remark";
import remarkHtml from "remark-html";
import {
  remarkLilypond,
  remarkGuitarChart,
  closeBrowser,
  type LilyPondOptions,
  type SVGuitarOptions,
} from "music-md";

const lilyOptions: LilyPondOptions = { compact: true };
const svguitarOptions: SVGuitarOptions = { keepAlive: true };

const processor = remark()
  .use(remarkLilypond, lilyOptions)
  .use(remarkGuitarChart, svguitarOptions)
  .use(remarkHtml, { sanitize: false });

const result = await processor.process(markdown);

// When using keepAlive you should close the browser manually after all processing:
await closeBrowser();

SVGuitar keepAlive Option

The keepAlive option (default false) trades memory for speed across multiple markdown files:

const processor = remark()
  .use(remarkGuitarChart, { keepAlive: true })
  .use(remarkHtml, { sanitize: false });

for (const file of files) {
  await processor.process(await fs.promises.readFile(file, "utf8"));
}

await closeBrowser(); // Important when keepAlive = true

| Scenario | Recommendation | | ------------------------- | ----------------------------------------------------------- | | Single file CLI run | leave keepAlive false | | Batch convert many files | set keepAlive: true | | Long-lived server process | set keepAlive: true and call closeBrowser() on shutdown |

License

ISC