Using glu

glu converts Markdown files to PDF or executes Lua scripts for programmatic typesetting. The mode is determined by the file extension:

glu document.md     # Markdown → PDF
glu script.lua      # Lua script → PDF

Command line reference

glu [options] <filename.md|filename.lua>

Options:
  -h, --help           Show this help
      --loglevel LVL   Set the log level (debug, info, warn, error)
  -q, --quiet          Suppress output on console
      --template       Apply Go template expansion (Markdown mode)
      --css FILE       Additional CSS file (Markdown mode)
      --markdown       Print expanded Markdown to stdout (debug)

Commands:
      help             Show the help message
      version          Print version and exit

By default, glu shows log output on the console and writes a log file (<filename>.log). Use --quiet to suppress console output.

Markdown mode

When you pass a .md file, glu converts it to PDF automatically. See Markdown mode for the full feature set (frontmatter, Lua blocks, custom CSS).

Lua script mode

When you pass a .lua file, glu executes it as a Lua script. The script has full control over the PDF output using the glu.frontend and other modules. This mode is for advanced use cases that require programmatic typesetting.

Hello world example explained

The sample program from the start page is analyzed here in detail. The program creates a PDF file with a single page containing some text.

local frontend = require("glu.frontend")

Loads the frontend module. All glu modules must be loaded with require().

local doc = frontend.new("hello.pdf")

Creates a new PDF document with the filename hello.pdf. The glu.frontend module is the main API for creating PDF documents with glu.

local ff = doc:new_font_family("text")
local fs = frontend.fontsource({ location = "fonts/CrimsonPro-Regular.ttf" })
ff:add_member(fs, "regular", "normal")

Fonts are organized in font families. A font family can have multiple members with different weights (regular, bold, etc.) and styles (normal, italic). Here we create a font family named “text” and add a single regular font.

local txt = frontend.text({
    font_family = ff,
    font_size = "12pt",
    color = "black"
})

Creates a text object with styling. Settings can be passed directly to the constructor. Text objects can contain strings and other text objects, allowing for nested formatting (e.g., italic text within a paragraph).

local str = [[The quick brown fox jumps over the lazy dog...]]
str = str:gsub("\n", " ")
txt:append(str)

Adds the text content to the text object. The append method accepts strings, other Text objects, VLists, or Tables.

local vlist = doc:format_paragraph(txt, "225pt", { leading = "14pt" })

The format_paragraph() function turns the text object into a vertical list (vlist) that can be placed on the page. The width is specified as the second argument, and optional settings like leading (line height) can be passed in a table.

local page = doc:new_page()
page.width = "210mm"
page.height = "297mm"
page:output_at("1cm", "28cm", vlist)
page:shipout()

Creates a new page, sets its dimensions to A4 size, and places the vertical list at the specified coordinates (1cm from the left, 28cm from the bottom).

All dimension parameters accept either numbers (interpreted as points) or strings with units like "12pt", "1cm", "10mm", or "1in".

doc:finish()

Finalizes the PDF document and writes it to the file.

Available modules

Module Description
glu Scaled point operations and logging
glu.frontend High-level typesetting API (documents, text, fonts, tables)
glu.pdf Low-level PDF writing module (baseline-pdf wrapper)
glu.node Node types (glyph, glue, kern, etc.) and list operations
glu.font Font instances and text shaping

All modules must be loaded with require():

local glu = require("glu")
local frontend = require("glu.frontend")
local pdf = require("glu.pdf")
local node = require("glu.node")
local font = require("glu.font")

The glu.frontend and glu.pdf modules are for document creation. The glu, glu.node, and glu.font modules provide low-level access to the typesetting engine for advanced use cases.