glu — Markdown to PDF
glu converts Markdown files to PDF. Write your content in Markdown, and glu handles fonts, layout, and page formatting automatically.
glu document.md # → document.pdfInstallation
Download the latest binaries at https://github.com/speedata/glu/releases/latest.
If you have a Go installation, you can also build from source:
git clone https://github.com/speedata/glu
cd glu
rake buildQuick start
Create a file hello.md:
---
title: Hello World
---
# Hello World
This is a **bold** and *italic* paragraph.
| Column A | Column B |
|----------|----------|
| Value 1 | Value 2 |Run with:
glu hello.mdThis produces hello.pdf — an A4 page with serif fonts, proper headings, and a formatted table. No configuration needed.
Dynamic content with Lua
glu supports embedded Lua for calculations, data processing, and dynamic content. If a file hello.lua exists alongside hello.md, it is loaded automatically:
hello.lua:
function greeting(name)
return "Hello, " .. name .. "!"
endhello.md:
# Welcome
{= greeting("World") =}The {= expr =} syntax inserts the result of any Lua expression. See Markdown mode for the full feature set including Lua code blocks, YAML frontmatter, and custom CSS.
Callbacks
glu provides a callback system for page-level events. For example, drawing a frame on every page:
local frontend = require("glu.frontend")
frontend.add_callback("pre_shipout", "frame", function(doc, page, pagenum)
-- draw decorations, add page numbers, etc.
end)Named callbacks can be ordered and removed dynamically. See Callbacks for details.
Documentation
- Markdown mode — Markdown to PDF conversion (frontmatter, Lua blocks, CSS)
- Callbacks — page event callbacks (pre_shipout)
- Using glu — command line options and general usage
- glu.frontend module — Lua typesetting API (documents, text, fonts, tables)
- glu.pdf module — low-level PDF writing
- xml.cxpath module — XPath XML querying
- Backend modules — glu, glu.node, glu.font
- glu.textshape module — low-level text shaping (HarfBuzz port)