On this page
Authoring variables
Rendering variables is <Markdown extensions={[variables({ data })]}>; see
Variable basics. Authoring them uses the package's
other extension, which runs in the editor.
Editing variables#
Variable support in the editor comes from an extension (there are no extra editor props for it).
import { MarkdownEditor } from '@react-markdown-kit/editor'
import { variableChips } from '@react-markdown-kit/variables/editor'
<MarkdownEditor
value={source}
onChange={setSource}
extensions={[variableChips({ variables: reportVariables, previewData: sampleCustomer })]}
/>In rich mode every placeholder shows up as a chip with its label (from the
variables metadata) and a sample-data preview. When you type a
placeholder it turns into a chip as soon as you type the closing }}, except
inside code. The toolbar also gets an insert-variable button, and a custom
toolbar can dispatch INSERT_VARIABLE_COMMAND from its own picker,
built from the same variables map.
| Option | Purpose |
|---|---|
variables | Metadata per path: label and group for chips and pickers |
previewData | Sample values shown on the chips. Never written back |
previewLocale | Locale used for preview formatting only |
previewTimeZone | Time zone used for preview formatting only |
formatters | Extra formatters offered as suggestions and used for preview |
variableChips() is one extension split into two halves that share a name. The root
entry exports the headless half (the variable node, its round-trip
serializer, and a renderer handler that shows an unresolved placeholder as
<span data-rmk-variable>); /editor wraps it with the chip, the typing
trigger and the command. Use whichever one your surface needs. A preset that
includes the editor version still renders and resolves correctly, and
variables({ data }) resolves chips like any other placeholder.
Preview never rewrites the source#
The whole feature is built around this rule. A variable node
stores the authored text plus path, formatter and argument, and
serializes from only those. previewData is for display and never feeds into
serialization.
Authored Hello {{customer.name}}
Rich mode Hello [ Customer name ]
Preview Hello Acme
Saved Hello {{customer.name}}If you change the preview customer, the saved source stays byte-for-byte the same. If the preview could edit the source, one wrong click could leave you with a document that says Acme to every customer.
The same goes for a failed preview. A sample value of the wrong type just shows no preview, and the placeholder isn't touched.
Hello {{customer.name}},
Your plan renews on {{renewsAt | date:"long"}} at {{price | currency:"USD"}} per seat.
Hello Acme Industrial,
Your plan renews on May 2, 2026 at $24.00 per seat.
The left pane is what an author edits and what gets stored in the database. The right pane is what each customer gets.
Placeholders survive source mode#
In source mode the editor shows the authored {{customer.name}} instead of
a preview value. Placeholders live inside text nodes, and the extension leaves
inline code, fenced code and raw HTML alone, so anything the editor draws as a
variable is something the engine would actually resolve.
Building your own picker#
Compile the source with variableChips() and no data. Every placeholder
turns into a variable node with path, formatter and argument,
and the variables metadata you passed in provides labels and groups. Then
insert whatever the user picks with INSERT_VARIABLE_COMMAND on the
native editor.
Next#
- Formatting and localization for formatter names.
- Security for what a runtime value is allowed to do.
Read next#
The overview, from placeholder syntax to schemas: Markdown variables.
Last updated on