@bangle.dev/core
@bangle.dev/core
as the name suggests is the core of Bangle and most packages expect it as a peer dependency. To install run:
💡 Use the right sidebar or the hamburger at bottom-right (mobile screens) to navigate quickly.
#
ComponentThe building block of Bangle is a component. At it's heart, we have a vanilla Javascript module which exports the follow properties:
?spec(opts: Object): Spec
The specification which defines how the component will be rendered in the Editor. If the component has nothing to render it will not export this method.?plugins(opts: Object): Plugins
This injects the superpowers 🧙♀️ to your component. Fantasy aside: you can pretty do anything to your node/mark with Plugins.?commands: CommandObject
?defaultKeys: KeybindingsObject
#
SpecAn object with the following fields:
type:
'node'
|'mark'
This is a Prosemirror concept which divides the spec in two groupsnode
type ormark
type. Please checkout Your first editor guide guide.topNode: ?boolean
Whether the node will be the top node for the document. By default thedoc
node is the top node for Bangle. There can only be one topnode
and is only applicable fornode
types.name: string
The name of the node or mark.schema: Prosemirror.NodeSpec | Prosemirror.MarkSpec
markdown: ?{toMarkdown: fn(), parseMarkdown: object}\
options: ?object
Use this to save data in this spec. You can use this field to save some data options to make it available to anyone having access to specRegistry.
#
Plugins🧠 Please note this is a recursive type - it contains reference to itself!
Prosemirror.Plugin | Plugins[] | (fn({ schema, specRegistry }) -> Plugins) | undefined
This is designed in a way to provide flexibility and extensibility when grouping multiple plugins under a Component. Please checkout this example on how to create a small plugin or read the source code of some of the core components.
#
Plugin#
KeybindingsObject{ [string]: string | undefined }
An object which defines the keybindings that are active for a given component. The keys are the name given to an action and the value is valid w3c-keyname. Setting a key to undefined will make it a no-op
.
In the example below, it tells that an action named moveUp
will be executed when a user presses Alt
and ArrowUp
key.
📖 Please checkout the Keybindings Guide
#
CommandObject{ [string]: fn(opts: object) -> Command }
A collection of commands exported by a component.
#
Commandfn(state: Prosemirror.EditorState, ?dispatch: ?fn(tr: Prosemirror.Transaction), ?view: Prosemirror.EditorView) -> boolean
A function that carries out a bunch of transformations in the editor. The return value indicates whether it was executed or not. For example, running a toggleBold command on a code block will return false
to indicate command did not execute, however it will return true
when run on a paragraph.
If a dispatch
callback is not passed, the command will run in dry run mode -- it will pretend to do things but will actually make no changes to the editor.
💡 Bangle's API will always export a higher order function which then returns a Command, which means it will not export a Command directly. It is designed this way to allow for configurability and to keep the command params predictable -- (config) => (state, dispatch, view) => boolean
.
Please read commands guide for more details.
#
QueryCommandfn(state: Prosemirror.EditorState) -> T
This is a special type of command which makes no changes to the editor but queries the editor state and returns the value.
💡 Bangle follows the convention of prefixing query
to any function that returns a QueryCommand.
In the example above, queryIsHeadingActive queries the editor state's selection for a node with name heading
having a level of 3
.
#
BangleEditornew BangleEditor(element, options)
Initializes and mounts the editor in your application. Create an editor instance with following params:
element: : dom.Node
options: Object
Has the following named parametersstate: BangleEditorState
The editor state object.focusOnInit: ?boolean=true
Focus the editor after initialization.pmViewOpts: ?Prosemirror.DirectEditorProps
An object containing PM's editor props.
The class exposes the following fields/methods:
focusView(): void
Focus the editor.destroy(): void
Destroy the editor instance.toHTMLString(): string
Returns the HTML representation of editors content.view: Prosemirror.EditorView
Usage
📖 See Bangle Markdown example
#
BangleEditorStatenew BangleEditorState(options)
Create an editor state instance with following params:
options: Object
specRegistry: ?SpecRegistry
The SpecRegistry of your editor. Note: you can either setspecRegistry
orspecs
but not both.specs: ?Spec[]
A shorthand which initializes SpecRegistry for you behind the scenes. Use this if you don't care about creating and managing a SpecRegistry instance. Note: you can either setspecRegistry
orspecs
but not both.plugins: ?Plugins[]
The list of plugins for your editor.initialValue: string | htmlString | undefined
The initial content of the editor.editorProps: Prosemirror.EditorProps
pmStateOpts: ?Prosemirror.EditorStateCreateConfig
The class exposes the following fields/methods:
specRegistry: SpecRegistry
pmState: Prosemirror.EditorState
Usage
See usage of BangleEditor.
#
SpecRegistrynew SpecRegistry(specs, options)
A wrapper class which sets up the Prosemirror.Schema. SpecRegistry combines and merges all the spec's of your components.
Params:
specs: ?Spec[]
An array containing the specs. Note: the order of specs matters.options: ?Object
- defaultSpecs: ?boolean=true
Automatically include critical specdoc
,text
¶graph
if they are not already provided in thespecs
param.
- defaultSpecs: ?boolean=true
The class exposes the following fields/methods:
schema: Prosemirror.Schema
The Prosemirror schema instance associated with the specRegistry. This comes in handy when dealing directly with Prosemirror libraries.options: Object<name, object>
A dictionary of the key value pair ofnode
ormark
name and the option field in their spec.
Usage
In the example below, we are loading a bunch of specs & plugins.
#
ComponentsThe following is a list of components exported by this package.
Component#
blockquote:Enables blockquote in your editor.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=true
Toggle the markdown shortcut for creating a blockquote. If enabled, type>
followed by a space to create one.
KeybindingsObject#
defaultKeys:wrapIn=
Ctrl-ArrowRight
: wrap text in blockquote.moveDown=
Alt-ArrowDown
: move blockquote downmoveUp=
Alt-ArrowUp
: move blockquote upemptyCopy=
Mod-c
: Execute a clipboard copy on the node when the selection is empty.emptyCut=
Mod-x
: Execute a clipboard cut on the node when the selection is empty.insertEmptyParaAbove=
Mod-Shift-Enter
: Inserts an empty paragraph above.insertEmptyParaBelow=
Mod-Enter
: Inserts an empty paragraph below.
CommandObject#
commands:- queryIsBlockquoteActive(): QueryCommand<boolean>
Query if the selection is inside a blockquote or not.
Usage
Component#
bold:Allows text in your editor to be marked as bold.
MarkSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=true
Toggle the markdown shortcut for creating a bold mark. If enabled, type**text**
to create the mark.
KeybindingsObject#
defaultKeys:- toggleBold =
Mod-b
: toggle bold mark
CommandObject#
commands:toggleBold(): Command
Toggles bold mark.queryIsBoldActive(): QueryCommand<boolean>
Query if the selection is inside a bold mark or not.
Usage
Component#
bulletList:Enables bulletList <ul/>
. Requires node components with names orderedList
& listItem
to work.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=
true
Enable the markdown shortcut for creating a bullet list. If enabled, type-
,*
or+
followed by a space to create a bullet list on an empty paragraph.
KeybindingsObject#
defaultKeys:- toggle=
Shift-Ctrl-8
: ExecutestoggleBulletList
command.
CommandObject#
commands:toggleBulletList(): Command
Convert to a bulletList and if already a bulletList, convert it to a paragraph node.queryIsBulletListActive(): QueryCommand<boolean>
Query if the selection is inside a bullet list.
Usage
Component#
code:Allows text in your editor to be marked as code.
MarkSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.escapeAtEdge: ?Boolean=true
Allows automatic escaping of code mark at the edges. This particularly helps to escape code mark by pressing left or right arrow key at the edges.markdownShortcut: ?Boolean=true
Toggle the markdown shortcut for creating a code mark. If enabled, type`text`
to create a code mark.
KeybindingsObject#
defaultKeys:- toggleCode =
Mod-`
: toggle code mark
CommandObject#
commands:toggleCode(): Command
Toggles code mark.queryIsCodeActive(): QueryCommand<boolean>
Query if the selection is inside a code mark or not.
Usage
Component#
codeBlock:Enables <code/>
in your editor.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?Boolean=true
Toggle the markdown shortcut for creating a codeBlock. If enabled, type```
to create one.
KeybindingsObject#
defaultKeys:toCodeBlock=
Shift-Ctrl-\
: wraps text in codeBlock.moveDown=
Alt-ArrowDown
: move codeBlock downmoveUp=
Alt-ArrowUp
: move codeBlock upinsertEmptyParaAbove=
Mod-Shift-Enter
: Inserts an empty paragraph above.insertEmptyParaBelow=
Mod-Enter
: Inserts an empty paragraph below.
CommandObject#
commands:- queryIsCodeActiveBlock(): QueryCommand<boolean>
Query if the selection is inside a codeBlock or not.
Usage
Component#
doc:Top level node needed by the editor to contain every other node. The spec & plugins for this component are required for Bangle to function, if a spec named doc
is not defined, Bangle will automatically default to this one.
NodeSpec#
spec():Returns a node spec with topNode set to true
, read more Your first editor guide.
Component#
heading:Enables headings of various levels in your editor .
NodeSpec#
spec({ ... }):Named parameters:
- levels: ?number[]=[1,2,3,4,5,6]
The allowed levels for the heading, think<h1/>
,<h2/>
and so on. The array must be contiguous and the first element must be1
and the last element must be less than or equal to6
.
Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?Boolean=true
Toggle the markdown shortcut for heading. If enabled, type#
followed by a space to create one a level one heading.
KeybindingsObject#
defaultKeys:toH1=
Shift-Ctrl-1
: Convert a node to heading of level 1. Is a no-op if the level1
is disallowed.toH2=
Shift-Ctrl-2
: Convert a node to heading of level 2. Is a no-op if the level2
is disallowed.toH3=
Shift-Ctrl-3
: Convert a node to heading of level 3. Is a no-op if the level3
is disallowed.toH4=
Shift-Ctrl-4
: Convert a node to heading of level 4. Is a no-op if the level4
is disallowed.toH5=
Shift-Ctrl-5
: Convert a node to heading of level 5. Is a no-op if the level5
is disallowed.toH6=
Shift-Ctrl-6
: Convert a node to heading of level 6. Is a no-op if the level6
is disallowed.moveDown=
Alt-ArrowDown
: move heading downmoveUp=
Alt-ArrowUp
: move heading upemptyCopy=
Mod-c
: Execute a clipboard copy on the node when the selection is empty.emptyCut=
Mod-x
: Execute a clipboard cut on the node when the selection is empty.insertEmptyParaAbove=
Mod-Shift-Enter
: Inserts an empty paragraph above.insertEmptyParaBelow=
Mod-Enter
: Inserts an empty paragraph below.toggleCollapse:
-
: Toggle collapsing of heading.
CommandObject#
commands:toggleHeading(level:
number=3
): Command
Toggles text into heading of a givenlevel
and vice versa.queryIsHeadingActive(level:
number=3
): QueryCommand<boolean>
Query if the selection is inside a heading of givenlevel
.queryIsCollapseActive(): Command
Query if the current heading is collapsed.collapseHeading(): Command
Hides every node below that is not heading or has a headinglevel
less than that of the current heading.uncollapseHeading(): Command
Brings back all the hidden nodes of a collapsed heading. Will only uncollapse shallowly i.e a collapse heading inside of a collapsed heading will not be uncollapsed.toggleHeadingCollapse(): Command
Collapses an uncollapsed heading and vice versa.uncollapseAllHeadings(): Command
Uncollapses all headings in thedoc
. Will also deep uncollapse every heading that was inside of a collapsed heading.
On Heading collapse
The heading component also allows you to collapse and uncollapse any content, after the current heading, that is not of type heading or has a heading of level greater than the current heading.
💡 The collapsed data is saved in the node attribute collapseContent
, it is also accessible inside the DOM data attribute by accessing data-bangle-attrs
.
💡 A collapsed heading will have a class name of bangle-heading-collapsed
to allow for styling.
⚠️ For serializing to Markdown you will have to uncollapse your document, since markdown doesn't support collapsing. You should run the commanduncollapseAllHeadings
before serializing to markdown.
On top of the collapse commands, the component also exports the following helper functions to help with collapse functionality:
listCollapsibleHeading(state: Prosemirror.EditorState): [{node: Prosemirror.Node, pos: number}]
Lists all the headings that can be collapsed or uncollapsed.listCollapsedHeading(state: Prosemirror.EditorState): [{node: Prosemirror.Node, pos: number}]
Lists all the headings that are currently collapsed.flattenFragmentJSON(fragmentJSON: Object): Object
Deep flattens any nested collapsed heading in the object. Bangle internally uses this to implementuncollapseAllHeadings
command. ExampleflattenFragmentJSON(node.attrs.collapseContent)
.
Usage
Component#
history:Enables history in your editor, this is a wrapper for the prosemirror's history module. Unless you are overriding this component, it will be included by default.
Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.historyOpts: Object
see the Prosemirror historyconfig
docs for the API.
KeybindingsObject#
defaultKeys:undo=
Mod-x
redo=
Mod-y Shift-Mod-z
CommandObject#
commands:Component#
hardBreak:Enables the <br />
element in your editor.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
- keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.
KeybindingsObject#
defaultKeys:- insert =
Shift-Enter
: inserts a hard break
Usage
Component#
horizontalRule:Enables a horizontal (<hr />
) rule component in your editor.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=true
Toggle the markdown shortcut for creating a horizontalRule. Type---
and___
to insert a horizontal rule.
Usage
Component#
image:Enables images in your editor.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.handleDragAndDrop: ?boolean=true
Toggle the functionality of dragging, dropping and pasting of images into the editor.
Usage
Component#
italic:Allows text in your editor to be marked as italic.
MarkSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=true
Toggle the markdown shortcut for creating am italic mark. If enabled, type_text_
to enable italic mark.
KeybindingsObject#
defaultKeys:- toggleItalic =
Mod-i
: toggle an italic mark
CommandObject#
commands:toggleItalic(): Command
Toggles italic mark.queryIsItalicActive(): QueryCommand<boolean>
Query if the selection is inside an italic mark or not.
Usage
Component#
link:Allows text in your editor to be marked as link.
MarkSpec#
spec({ ... }):Named parameters:
- openOnClick: ?boolean=false
If enabled clicking a link will open the link in new tab. If disabled, clicking a link will set the cursor on it.
Plugins#
plugins():CommandObject#
commands:createLink(href : string): Command
Creates a link mark on the selection text.updateLink(href : ?string): Command
Updates a link mark on the selection text withhref
. Sethref
toundefined
to clear the link mark. If selection is empty, it will update the parent text node.queryLinkAttrs(): QueryCommand<?{href: string, text: string}>
Returns the details of the link mark in selection.queryIsLinkAllowedInRange(from: number, to: number): QueryCommand<boolean>
Queries if the range allows for creation of link mark.queryIsLinkActive(): QueryCommand<boolean>
Queries if the selection is in a link mark.queryIsSelectionAroundLink(): QueryCommand<boolean>
Queries if the selection is around a link mark.
Usage
Component#
listItem:Creates a listItem <li/>
. Requires node components with names bulletList
and orderedList
to work
NodeSpec#
spec({ ... }):Plugins#
plugins({ ... }):Named parameters:
- keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.
KeybindingsObject#
defaultKeys:indent=
Tab
: Indents the listItemoutdent=
Shift-Tab
: Outdents the listItemmoveDown=
Alt-ArrowDown
: move listItem downmoveUp=
Alt-ArrowUp
: move listItem upemptyCopy=
Mod-c
: Execute a clipboard copy on the node when the selection is empty.emptyCut=
Mod-x
: Execute a clipboard cut on the node when the selection is empty.insertEmptyListAbove=
Mod-Shift-Enter
: Insert a new list above the current list and move cursor to it.insertEmptyListBelow=
Mod-Enter
: Insert a new list below the current list and move cursor to it.
CommandObject#
commands:indentListItem(): Command
Indents list item one level. Can only indent 1 plus the parent's level.outdentListItem(): QueryCommand<boolean>
Outdents list item one level. If level is root, outdents to a paragraph.
Usage
Component#
orderedList:Enables orderedList <ol/>
. Requires node components with names bulletList
, listItem
to work.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=true
Enable the markdown shortcut for creating an ordered list. Type1.
followed by a space to create an ordered list.
KeybindingsObject#
defaultKeys:- toggle=
Shift-Ctrl-9
: ExecutestoggleOrderedList
command.
CommandObject#
commands:toggleOrderedList(): Command
Convert to an orderedList and if already an orderedList, convert it to a paragraph node.queryIsSelectionInsideOrderedList(): QueryCommand<boolean>
Query if the selection is inside an ordered list.
Usage
Component#
paragraph:Enables paragraph (<p/>
in html) nodes in your editor. The spec for this component are required for Bangle to function, if a spec with a name=paragraph
is not specified, Bangle will automatically default to this one.
NodeSpec#
spec():Returns a spec, read more Your first editor guide.
Plugins#
plugins({ ... }):Named parameters:
- keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.
KeybindingsObject#
defaultKeys:jumpToStartOfParagraph=
Ctrl-a (mac) Ctrl-Home (linux/pc)
: Executes thejumpToStartOfParagraph
command (see commands below).jumpToEndOfParagraph=
Ctrl-a (mac) Ctrl-Home (linux/pc)
: Executes thejumpToEndOfParagraph
command (see commands below).moveDown=
Alt-ArrowDown
: Move paragraph down.moveUp=
Alt-ArrowUp
: Move paragraph up.emptyCopy=
Mod-c
: Execute a clipboard copy on the node when the selection is empty.emptyCut=
Mod-x
: Execute a clipboard cut on the node when the selection is empty.insertEmptyParaAbove=
Mod-Shift-Enter
: Inserts an empty paragraph above.insertEmptyParaBelow=
Mod-Enter
: Inserts an empty paragraph below.convertToParagraph=
Ctrl-Shift-0
: Toggles a node to paragraph and vice versa.
CommandObject#
commands:jumpToStartOfParagraph(): Command
Jumps the cursor to the start of paragraph.jumpToEndOfParagraph(): Command
Jumps the cursor to the end of paragraph.convertToParagraph(): Command
Coverts the node in selection to paragraph type.queryIsParagraph(): QueryCommand<boolean>
Query if it is paragraph under the selection.queryIsTopLevelParagraph(): QueryCommand<boolean>
Query if it is paragraph under the selection and it is a direct descendant of the top level node, which by default is doc.
Usage
Component#
strike:Allows text in your editor to be marked as strike.
MarkSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
- keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.
KeybindingsObject#
defaultKeys:- toggleStrike =
Mod-d
: toggle a strike mark
CommandObject#
commands:toggleStrike(): Command
Toggles strike mark.queryIsStrikeActive(): QueryCommand<boolean>
Query if the selection is inside a strike mark or not.
Usage
Component#
text:The text node which the editor uses to wrap the text. The spec for this component are required for Bangle to function, if a spec named text
is not defined, Bangle will automatically default to this one.
NodeSpec#
spec():Creates a todoItem node spec with done
attribute, read more Your first editor guide.
Component#
todoItem:Creates a todoItem with a done
attribute. Requires node components with names todoList
, bulletList
,orderedList
& listItem
to work
NodeSpec#
spec({ ... }):Named parameters:
nested: boolean=true
Allows nesting of todo items.draggable: boolean=true
Make todo items draggable.
Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.nodeView: boolean=true
Iftrue
, will use the default todoItem nodeView. Set it tofalse
to disable the default todoItem nodeView. The typical use-case for setting it tofalse
is when you want to use a custom nodeView for todoItem. See the section for more details.
KeybindingsObject#
defaultKeys:toggleDone=
Ctrl-Enter (mac) Ctrl-I (linux/windows)
: Toggles the todo item's done status.indent=
Tab
: Indents the todo itemoutdent=
Shift-Tab
: Outdents the todo itemmoveDown=
Alt-ArrowDown
: move todoItem downmoveUp=
Alt-ArrowUp
: move todoItem upemptyCopy=
Mod-c
: Execute a clipboard copy on the node when the selection is empty.emptyCut=
Mod-x
: Execute a clipboard cut on the node when the selection is empty.insertEmptyParaAbove=
Mod-Shift-Enter
: Inserts an empty paragraph above.insertEmptyParaBelow=
Mod-Enter
: Inserts an empty paragraph below.
CommandObject#
commands:toggleTodoItemDone(): Command
Toggle the done attribute of the todo item in the selection.queryTodoItemAttrs(): QueryCommand<?{done: boolean}>
Query the todo item attributes.
Usage
Component#
todoList:A wrapper node component for todoItem
, similar to how orderedList
is a wrapper for listItem
. Requires node components with names todoItem
, bulletList
,orderedList
& listItem
to work.
NodeSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.markdownShortcut: ?boolean=true
Enable the markdown shortcut for creating a todo list. Type[ ]
or[]
followed by a space to create an unchecked todoList.
KeybindingsObject#
defaultKeys:- toggle=
Shift-Ctrl-7
: ExecutestoggleTodoList
command.
CommandObject#
commands:toggleTodoList(): Command
Convert to an todoList and if already an todoList, convert it to a paragraph node.queryIsTodoListActive(): QueryCommand<boolean>
Query if the selection is inside a todo list.
Usage
See todoitem usage.
Component#
underline:Allows text in your editor to be marked with underlined style.
MarkSpec#
spec():Plugins#
plugins({ ... }):Named parameters:
- keybindings: ?KeybindingsObject=defaultKeys
For a list of allowed keys see defaultKeys below.
KeybindingsObject#
defaultKeys:- toggleUnderline =
Mod-u
: toggle an underline mark
CommandObject#
commands:toggleUnderline(): Command
Toggles underline mark.queryIsUnderlineActive(): QueryCommand<boolean>
Query if the selection is inside an underline mark or not.
Usage