Skip to content

The shortcut system

Shortcuts are how you style content in Keystone. When you write a fenced div, a bracketed span or a heading with a class name, you're invoking a shortcut:

::: dialog
- Who's there?
- Just the wind.
:::

A word in [small caps]{.font style="bold"} mid-sentence.

dialog and font are shortcuts. Keystone ships a complete set of them — the system shortcuts — and you can define your own on top.

Two layers

  • System shortcuts ship with Keystone and cover every built-in styling capability: font, align, figure, aside, dialog, quote, and the rest. They're always available — you don't declare them. The reference lists them all.
  • User shortcuts are yours, defined in shortcuts.yaml. They build on the system shortcuts to create project-specific vocabulary — define garamond once instead of repeating font family="eb-garamond" everywhere. See Writing your own shortcuts.

How you use them

Shortcuts are written like any Pandoc class, in the forms the Markup syntax page covers in full. Most are block-level:

  • As a fenced div — ::: name … ::: — for block content (paragraphs, lists, images).

Some also work inline, as a bracketed span — [text]{.name} — for runs inside a paragraph. Inline support is per-shortcut (font, dropcap, set, the conditional shortcuts, and a few others); the reference notes which. A heading takes a shortcut of your own built on container — see Headings.

Most shortcuts accept attributes that tune their behavior, written in the Pandoc attribute syntax:

::: {.font family="eb-garamond" size="large"}
A passage in large EB Garamond.
:::

Each shortcut's reference entry lists the attributes it accepts and their defaults. An attribute the shortcut doesn't recognize produces a build warning — that's typo detection, not a hard failure.

Build on the stable layer

The system shortcuts are a public promise: once a shortcut, one of its attributes or a form it renders ships, it's never removed or renamed. What counts as valid markup can tighten, only in a release marked breaking, whose changelog says what to change.

Behind each system shortcut is an internal handler whose class starts with the reserved ks- prefix (font → ks-font). Those handlers are private and carry no such promise — they can change or disappear between releases. You reach a handler through the system shortcut that fronts it, and build your own shortcuts on the system names too. The system layer absorbs internal changes so your manuscript doesn't have to.

Reserved prefix

Expansion writes the ks- classes, so you never do: a ks- class in your manuscript stops the build, and so does the prefix anywhere in shortcuts.yaml.