Extensions manage similar concerns. It allows for grouping items that affect:
- How the editor displays certain content, i.e. bold, italic, underline.
- Makes certain commands available e.g.
commands.toggleBold()to toggle the bold formatting of the currently selected text.
- Check if a command can be run for the current selection
- Check if a mark is active at the current selection,
- Register ProseMirror plugins, keymaps, input rules, paste rules, and custom nodeViews, which affect the behaviour of the editor.
There are three types of
NodeExtension- For creating ProseMirror nodes in the editor.
MarkExtension- For creating ProseMirror marks in the editor.
PlainExtension- For behaviour which doesn't need to be displayed in the DOM.
Extensions are able to completely customise the behaviour of the editor via these lifecycle methods. Even core functionality like the creation of
Schema is built via
Extensions. This section outlines what you're working with in extensions.
This handler is called when the
RemirrorManager is first created. Since it is called as soon as the manager is created some methods may not be available in the extension store. When accessing methods on
this.store be sure to check their documentation for when they become available. It is recommended that you don't use this method unless absolutely required.
This lifecycle method is called when the
EditorView is first added by the UI layer. This is the lifecycle method where commands and editor helpers are added.
This is called whenever a transaction successfully updates the
EditorState. For controlled component this is called whenever the state value is updated.
This is called when the
RemirrorManager is being destroyed. You can use this method if you need to clean up any externally created handlers in order to prevent memory leaks.
Options are used to configure the extension at runtime. They come in four different flavours via the option annotations.
These annotations can be used to provide better intellisense support for the end user.
The extension decorator updates the static properties of the extension. If you prefer not to use decorators it can also be called as a function. The
Extension constructor is mutated by the function call.
Dynamic options can be passed in at instantiation and also during runtime. When no annotation exists the option is assumed to be dynamic.
Please note that as mentioned in this issue #624, partial options can cause trouble when setting a default.
If you need to accept
undefinedas an acceptable default option there are two possible ways to resolve this.
This is the preferred solution and should be used instead of the following
Now when the options are consumed by this decorator there should be no errors when setting the value to
If you don't mind using nulls in your code then this might appeal to you.
Static options should be used when it is not possible to update an option during runtime. Typically this is reserved for options that affect the schema, since the schema is created at initialization. They will throw an error if an error if updated during runtime.
Handler options are a pseudo option in that they are completely handled by the underlying remirror extension.
To get them to work we would change the above example extension implentation to look like the following.
Now that the extension is wired to respond to
onChange handlers we can add a new handler.
The onChange handler is automatically managed for you.
CustomHandler options are like
Handler options except it's up to the extension creator to manage how they are handled. They are useful for situations when you want the extension to allow composition of events but it doesn't quite fit into the neat
The KeymapExtension in
@remirror/core is a good example of this.