Skip to content

The AST library (KAST)

Pandoc represents your document as an abstract syntax tree (AST) — the nodes a Lua filter reads and rewrites. In Keystone, every handler and filter goes through a single library to touch that tree: KAST (Keystone AST). Instead of calling Pandoc's constructors, readers, writers, and walkers directly, code acquires KAST with ks_require("ast") and works through it.

One seam, for two reasons:

  • Consistency — constructing, serializing, and inspecting the AST happens one way across the whole engine, so handlers compose and behave predictably.
  • Insulation — when Pandoc's API shifts, the change is absorbed in one place rather than scattered through every handler.

By convention, no file outside the AST library names Pandoc's constructors, read / write, utils, or :walk directly — they all go through KAST. (The host surface Pandoc hands the script — FORMAT, pandoc.path, system, yaml — is exempt.) In the canonical project this rule is enforced; in your copy of the engine it's simply the discipline the code follows, and matching it keeps your changes consistent with everything around them.

The practical upshot when you work in the engine: you'll see KAST throughout the handlers, and when you write or edit one, you reach for it the same way they do rather than for pandoc.*. The existing handlers are the working examples.