RTInlineElementConfig

Configuration for registering inline rich text element types.

In rich text documents, inline elements such as links, equations, etc. are defined using RTInlineElement objects. Before such elements can be created, the element type needs to be registered using the RTElements.register method.

Inline level elements are rendered inline with text, as part of another (block or inline) element's children. An inline element can only be siblings with RTNodes and other RTInlineElements.

The configuration object for registering new inline level element types. See below the table for additional details.

PropertyTypeDescription
level*'inline'The level at which the element is rendered, always 'inline'.
type*stringThe element type, such as 'equation'.
component*React.ComponentTypeThe component used to render the element.
initializeDataFromFragmentfunctionCalled when creating a new element of this type from a rich text fragment. Should return the initial state of any custom data used in the element. Can be omited if the element simply uses the fragment as its children or not at all.
toPlainTextfunctionFunction which returns a plain text version of the element's content.
voidbooleanDetermines whether the element is editable within the editor text flow.
shortcuts| (string
| InlineShortcutWrapTrigger)[]
Markdown style shortcuts which trigger the insertion of this element.
hotkeysInlineHotkey[]A list of keys which, when pressed in unison, insert an element of this type.
htmlDeserializersHtmlDeserializerMapDeserializer functions used to deserialize pasted HTML into this type of element.

Inline rich text element components are just simple React components. However, there are two required props which need to be applied correctly in order for the element to function:

  • attributes: contains HTML attributes used internally by the editor, must be spread onto the root HTML element.

  • children: renders the RTFragment containing the text content. Must be rendered within the component, even if the component does not have children.

Below is an example of a non-void (in which text can be edited) link element. It will render a link for which the text can be edited.

interface LinkElementProps extends RTInlineElementProps {
/**
* The link URL.
*/
url: string;
}
const LinkElement: React.FC<LinkElementProps> = ({ attributes, children, element, }) => (
<a href={element.url} {...attributes}>
{children}
</a>
);

Below is an example of a void (in which there is no text to edit) equation element in which the actual equation rendering is carried out by another component. Note that children needs to be rendered despite the quation itself not being editable within the editor flow (it will render an empty span element required for editor functionality).

interface EquationElementProps extends RTInlineElementProps {
/**
* The image src.
*/
src: string;
}
const EquationElement: React.FC<EquationElementProps> = ({ attributes, children, element, }) => (
<span {...attributes}>
<Equation expression={element.expression} />
{children}
</span>
);

RTInlineElementProps

The props passed to inline element components.

PropertyTypeDescription
attributes*Record<string, string>HTML attributes required for the editor to function. Should be spread onto the root HTML element of the component.
children*React ChildrenRenders the editable rich text content. Must be rendered even if the element is void and does not support rich text content (it will render an empty span element required for editor functionality).
element*RTElementThe rich text element being rendered.

Called when creating a new element of this type. Should return an object containing the initial state of the custom data used in the element. Omit if the element does not use custom data.

initializeData<TData extends {}>(fragment?: RTFragment): TData
ArgumentTypeDescription
fragmentRTFragmentThe text fragment selected in the editor.

If there is a selection in the editor when the element is created (e.g. the user selects text and presses the element's creation hotkey), the fragment parameter will contain a RTFragment (see the RTFragment page for details). The fragment will automatically be set as the element's children field unless the element is void.

Example

For an 'equation' element which stores the equation expression under a field called expression, the initializeData method should return an object initializing the property:

initializeData: (fragment) => ({
expression: fragment ? RTElements.toPlainText(fragment) : '',
});

In this example, if a fragment is present, expression is initialized with the fragment's plain text value (and an empty string otherwise).

A function which returns a plain text version of the element's content. Only needed for void elements which use text based data (e.g. a 'equation' element in which the equation expression is edited in a popup field).

Providing a toPlainText method is strongly recommended for void elements which contain any text based data. The method has several uses:

  • Search: MindDrop's search indexing uses the plain text version of rich text documents. Providing a toPlainText method makes void elements searchable.

  • Copy/Paste: When copying text from the rich text editor, a plain text version of the text is added to the clipboard data.

  • Unregister: When an inline rich text element type is unregistered (e.g. because the extension was uninstalled), the elements of that type are converted into RTNodes with the plain text set as their text value.

toPlainText(element: RTInlineElement): string
ArgumentTypeDescription
element*RTInlineElementThe element to convert to plain text.

Void elements are elements which do not involve text (e.g. an image element), or elements in wich the text is not edited as part of the editor text flow (e.g. an equation element in which the equation expression is edited in a popup field).

Non-void elements must have a children field set to a RTFragment.

Markdown style shorcuts which trigger the insertion of an element of this type.

Inline element shortcuts can be one of two types:

  • A simple string, which triggers the shortcut as soon as it is typed.

  • A { start: string; end: string; } combo, which is triggered when the end string is typed some time after the start string (e.g. **bold text**).

The shortcut text is automatically removed when the shortcut is triggered.

InlineShortcutWrapTrigger

PropertyTypeDescription
start*stringThe shortcut start trigger.
end*stringThe shortcut end trigger.

The hotkeys related to this element. Inline element hotkeys can be used to insert a new element of this type, or modify the data of an existing element of this type if it is currently focused.

Hotkeys are configured using InlineHotkey objects with a keys property, which is the list of keys which when pressed together trigger the action, and an action property. The action property can be one of two types:

  • 'insert': setting the action to 'insert' will insert a new element of this type. If the hotkey is triggered with a text selection, initializeDataFromFragment will be called with the rich text fragment to initialize the new element's data.

  • InlineHotkeyAction: setting the action a function will call the function when triggered. It is only triggered if the currently selected/focused element(s) are of this type. The function should return updated custom data for the element type. If multiple elements are selected, the function is called once per element of this type.

Modifier keys:

  • Use 'Ctrl' for the Control key (maps to Command key on Mac)

  • Use 'Alt' from the Alt key (maps to the Option key on Mac).

  • Use 'Shift'for the Shift key.

For other keys, simply use the character itslef (e.g. 'A', '1', '#'). These are case insensitive.

For instance, the hotkey ['Ctrl', 'Shift', '1'] would trigger when the Control + Shift + 1 (Command + Shift + 1 on Mac) keys are pressed in unison.

Example

The following hotkey toggles a focused to-do element's 'done' state using Ctrl + Enter.

{
keys: ['Ctrl', 'Enter'],
action: (element) => ({ done: !element.done }),
}

InlineHotkey

PropertyTypeDescription
keys*string[]List of keys used to trigger the action.
action'insert' | InlineHotkeyActionThe action triggered by the hotkey.

InlineHotkeyAction

Callback fired when an inline hotkey is triggered. Should return the custom type data to set onto the element.

<TTypeData extends RTElementTypeData>(
core: Core,
element: RTInlineElement,
): TTypeData;
ArgumentTypeDescription
core*CoreA MindDrop core instance.
element*RTInlineElementThe target inline element on which the hotkey was triggered.

HTML deserializers are called when HTML data is inserted into the editor, usually as a result of text being copy pasted into the editor from a web page. They should return an object (or array of objects) containing the element type as well as any data used by the element, or null if an element should not be created.

HTML deserializers are configured using a { [node name]: HtmlDeserializer } map, where [node name] corresponds to an HTML element node name (in all caps), such a SPAN, A, IMG, etc. Use an asterisk (*) as the node name in order to match against all HTML element types. If multiple registered rich text element types configure a deserializer for the same HTML element, the deserializers will be run one after the other (in the order they were registered) until a non null value is returned. HTML deserializers bubble up, meaning that the most deeply nested elements are deserialized first, followed by their parent element.

The example below demonstrates an HTML deserializer which turns anchor elements (<a href="...">) into a 'link' element. Note that for non-void elements, children will be automatically added to the resulting element.

deserializers = {
A: (element) => {
if (element.href) {
// Only create a 'link' element if the achor has an href value
return { type: 'link', url: element.href };
}
// Don't create a 'link' element
return null;
},
};

HtmlDeserializer

Callback used to deserialize an HTML element.

deserializeHtmlElement(
element: HTMLElement,
parent: HTMLElement | null,
children: RTFragment | RTBlockElement[] | null,
): CreateRTInlineElementData | CreateRTInlineElementData[] | null
ArgumentTypeDescription
element*HTMLElementThe HTML element to deserialize.
parent*HTMLElement | null The element's parent element, or null if it has no parent.
children*| RTFragment
| RTBlockElement[]
| null
The element's deserialized child elements or null if the element has no children.