Your first Bangle Editor
To get started with your first Bangle Editor let us buld an editor which supports bold
and headings
.
- Example
- Source code
There is a lot going on in the above example, so lets distill it down into smaller parts:
- Components:
heading
,bold
- specs:
heading.spec()
,bold.spec()
- plugins:
heading.plugins()
,bold.plugins()
- initialValue:
Hello world!
#
Bangle componentA component is an object which hold smaller related things to form the building block of your editor. Let us look at high level overview of the bold
component:
export const bold = { spec(opts) { type: 'mark', name: 'bold', schema: { ... }, markdown: { ... } }, plugins(opts) { return [ ... ] }, commands: { toggleBold: () => { .... }, ... }}
#
SpecRegistryShort for specification, is an object that declaratively defines how your editor behaves, looks, its relationship with other entities and the parsing/serialization aspect of it. You can either create a SpecRegistry instance yourself or pass an array of specs and let Bangle create it for you internally.
const specs = [bold.spec()];const state1 = new BangleEditorState({ specRegistry: new SpecRegistry(specs), ...});const state2 = new BangleEditorState({ specs: specs ...});// state1 and state2 are essentially different// ways to do the same thing
💡 The specs: [...]
style should fit majority of use cases. The new SpecRegistry
syntax comes in handy when dealing with multiple syncronized editors which need to rely on a single instance of specRegistry
or if your application needs access to {{core.links.Prosemirror.Schema}}.
You might have noticed that we are using an array to order the specs. For most use cases the order doesn't matter,
however if two or more specs are competing, for example, a link spec vs bold spec, putting link spec before bold ensures
that your output will look like <bold>will wrap <a href="hola">a link tag</a>
.
📖 Handy links:
#
PluginsPlugins allow you to add interactivity to your editor. They allow for things like keyboard shortcuts, drag-n-drop, paste, etc.
💡 Not every component has .plugin()
, as some components are pretty simple, check the API doc of each component before using.
💡 There is no explicit connection between a component's plugins
and spec
, so feel free to mix, match them or even replace them with your own.
📖 Creating a custom component is a slightly complex topic, as you can pretty much do anything with plugins. Only dig deeper into plugin API if you want to build your own plugins, here are some handy links:
- Plugins API
- Simply put, plugins are just an array of Prosemirror.Plugin.
#
initialValueBangle accepts variety of things as initial value.
- You can use a vanilla string:
new BangleEditorState({ initialValue: `Hello world`,});
- You can use an html string. Check out persist to localStorage example for more details.
new BangleEditorState({ initialValue: `<div><p>Hello world</p></div>`,});
- Or a JSON doc. Check out persist to localStorage example for more details.
new BangleEditorState({ initialValue: { type: 'doc', content: [ { type: 'paragraph', content: [ { type: 'text', text: 'Hello world', }, ], }, ], },});