Styling
Variables are inline, non-editable nodes. Style the default view or extend Variable with your own NodeView.
Default markup and styling
<span data-type="variable" data-variable="greeting" contenteditable="false">Hello, Ada!</span>| Attribute | Value |
|---|---|
data-type | Always 'variable'. |
data-variable | The variable name, or '' when unset. |
contenteditable | Always 'false'. |
There are no default CSS classes or styles. Add outer-element attributes with HTMLAttributes (Record<string, string>, default {}):
Variable.configure({
HTMLAttributes: { class: 'my-variable' },
})Style .my-variable or [data-type='variable'] in your stylesheet. Required attributes take precedence. ProseMirror may add ProseMirror-selectednode when selected.
Custom NodeViews
Register your customized extension instead of Variable:
const CustomVariable = Variable.extend({
addNodeView() {
return ReactNodeViewRenderer(MyVariableView)
},
})ReactNodeViewRenderer comes from @tiptap/react. JavaScript and Vue use their standard Tiptap NodeView APIs.
- Keep the
variablenode name,nameattribute, and inline, atomic behavior. - Use a non-editable
spanwrapper withoutcontentDOMorNodeViewContent. - Read the initial value with
getVariable({ editor, name }). Subscribe tovariablesUpdateto refresh it; values can change without changing node attributes. - Your view owns its markup and attributes. Remove listeners and rendered content when it is destroyed.
Render a value
The default view renders Tiptap JSON with the editor's custom NodeViews, ordinary objects as JSON text, and other values as text. Use the same helper in your own view:
import { renderVariableValue } from '@tiptap-pro/extension-variable'
const rendered = renderVariableValue({ editor, value })
container.replaceChildren(rendered.dom)Before replacing the result or removing your view, release its nested NodeViews:
rendered.destroy()This renders a snapshot. Render again when the value changes. Nested NodeViews receive undefined from getPos() because the value is outside the document. See the helper's types.
HTML serialization
addNodeView controls the editor UI. renderHTML exports only an empty reference and any configured HTMLAttributes:
<span name="greeting" data-type="variable"></span>The name attribute preserves the variable name; data-type identifies it to the parser. View-only attributes and values are not exported. Custom renderHTML and parseHTML implementations should preserve this behavior.
Bound slots use Slot rendering. Slots controlled by an explicit value or resolver receive contenteditable="false", aria-readonly="true", and data-variable-readonly="true" in the editor.
Content Protection replaces concealed references with its own view; always read current values with getVariable so concealed values stay hidden.