Merge branch 'main' into develop

This commit is contained in:
Nick the Sick 2024-07-02 16:21:06 +02:00
commit c96d332364
No known key found for this signature in database
GPG Key ID: F575992F156E5BCC
246 changed files with 369 additions and 13388 deletions

3
.github/CODEOWNERS vendored
View File

@ -1,9 +1,6 @@
# Global
* @bdbch @svenadlung
# docs
/docs/ @svenadlung
# demos
/demos/ @bdbch

View File

@ -1,21 +0,0 @@
# Automate, customize, and execute your software development workflows right in your repository with GitHub Actions.
# Documentation: https://docs.github.com/en/actions
name: deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Update the documentation
run: curl ${{ secrets.TRIGGER_DEPLOYMENT }}

View File

@ -1,27 +0,0 @@
# Automate, customize, and execute your software development workflows right in your repository with GitHub Actions.
# Documentation: https://docs.github.com/en/actions
name: docsearch
on:
workflow_dispatch:
schedule:
- cron: '5 0 * * *'
jobs:
docsearch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.4
- name: Run DocSearch Scraper
shell: bash
run: |
docker run \
-e TYPESENSE_API_KEY=${{ secrets.TYPESENSE_API_KEY }} \
-e TYPESENSE_HOST="${{ secrets.TYPESENSE_HOST }}" \
-e TYPESENSE_PORT="${{ secrets.TYPESENSE_PORT }}" \
-e TYPESENSE_PROTOCOL="${{ secrets.TYPESENSE_PROTOCOL }}" \
-e CONFIG="$(cat docsearch.config.json | jq -r tostring)" \
typesense/docsearch-scraper

View File

@ -28,7 +28,7 @@
"@sveltejs/vite-plugin-svelte": "^2.0.0",
"@types/uuid": "^8.3.4",
"@vitejs/plugin-react": "^1.3.2",
"@vitejs/plugin-vue": "^1.10.2",
"@vitejs/plugin-vue": "^5.0.5",
"autoprefixer": "^10.4.2",
"iframe-resizer": "^4.3.2",
"postcss": "^8.4.31",

View File

@ -1,50 +0,0 @@
---
tableOfContents: true
---
# About the project
## Introduction
To deliver a top-notch developer experience and user experience, we put ~~hundreds~~ thousands of hours of unpaid work into Tiptap. Your funding helps us to make this work more and more financially sustainable. This enables us to provide helpful support, maintain all our packages, keep everything up to date, and develop new features and extensions for Tiptap.
Give back to the open source community and [sponsor us on GitHub](https://github.com/sponsors/ueberdosis)! ♥
## Your benefits as a sponsor 💖
* Your issues and pull requests get a `sponsor ♥` label
* Get a sponsor badge in all your comments on GitHub
* Invest in the future of Tiptap
* Give back to the open source community
* Show support in your GitHub profile
Sounds good? [Sponsor us on GitHub!](https://github.com/sponsors/ueberdosis)
## The maintainers of Tiptap
!!team-grid
## More peace of mind
Companies betting on Tiptap probably want some peace of mind and ensure that we keep maintaining Tiptap, but dont forget that our work is based on the work of other lovely people that you should definitely sponsor too:
* [Sponsor Marijn Haverbeke](https://marijnhaverbeke.nl/fund/) (ProseMirror)
## Frequently asked questions
### I cant use GitHub. How can I support you?
If youre a company, dont want to use GitHub, dont have a credit card or want a proper invoice from us, just reach out to us at [humans@tiptap.dev](mailto:humans@tiptap.dev).
We have an [OpenCollective](https://opencollective.com/tiptap), which allows you to send money through transfer, PayPal or credit card. Donations are tax deductible for US companies.
### I want consulting. Whats your rate?
If you have an issue, a question, want to talk something through or anything else, [please use GitHub issues](https://github.com/ueberdosis/tiptap/issues/new/choose) to keep everything accessible to the whole community. For everything else, reach out to [humans@tiptap.dev](mailto:humans@tiptap.dev). We can take on a limited number of custom development and consulting contracts.
### Can we have a call?
Nope, we are big fans of asynchronous communication. If you really need to reach out in private, send us an email to [humans@tiptap.dev](mailto:humans@tiptap.dev), but dont expect technical email support. That all happens on [GitHub](https://github.com/ueberdosis/tiptap/issues)
## P.S. Did you know, were also into realtime text editing?
With [Collaboration](https://tiptap.dev/collab) we built a realtime backend for conflict-free text editing. And the best part: Integration into Tiptap is just a few clicks away.
Make sure to check it out!
!!tiptap-collab-cta

View File

@ -1,27 +0,0 @@
# Introduction
Tiptap is a friendly wrapper around [ProseMirror](https://ProseMirror.net). Although Tiptap tries to hide most of the complexity of ProseMirror, its built on top of its APIs and we recommend you to read through the [ProseMirror Guide](https://ProseMirror.net/docs/guide/) for advanced usage.
### Structure
ProseMirror works with a strict [Schema](/api/schema), which defines the allowed structure of a document. A document is a tree of headings, paragraphs and others elements, so called nodes. Marks can be attached to a node, e. g. to emphasize part of it. [Commands](/api/commands) change that document programmatically.
### Content
The document is stored in a state. All changes are applied as transactions to the state. The state has details about the current content, cursor position and selection. You can hook into a few different [events](/api/events), for example to alter transactions before they get applied.
### Extensions
Extensions add [nodes](/api/nodes), [marks](/api/marks) and/or [functionalities](/api/extensions) to the editor. A lot of those extensions bound their commands to common [keyboard shortcuts](/api/keyboard-shortcuts).
## Vocabulary
ProseMirror has its own vocabulary and youll stumble upon all those words now and then. Here is a short overview of the most common words we use in the documentation.
| Word | Description |
| ----------- | ------------------------------------------------------------------------ |
| Schema | Configures the structure your content can have. |
| Document | The actual content in your editor. |
| State | Everything to describe the current content and selection of your editor. |
| Transaction | A change to the state (updated selection, content, …) |
| Extension | Registers new functionality. |
| Node | A type of content, for example a heading or a paragraph. |
| Mark | Can be applied to nodes, for example for inline formatting. |
| Command | Execute an action inside the editor, that somehow changes the state. |
| Decoration | Styling on top of the document, for example to highlight mistakes. |

View File

@ -1,323 +0,0 @@
---
tableOfContents: true
---
# Commands
## Introduction
The editor provides a ton of commands to programmatically add or change content or alter the selection. If you want to build your own editor you definitely want to learn more about them.
## Execute a command
All available commands are accessible through an editor instance. Lets say you want to make text bold when a user clicks on a button. Thats how that would look like:
```js
editor.commands.setBold()
```
While thats perfectly fine and does make the selected bold, youd likely want to chain multiple commands in one run. Lets have a look at how that works.
### Chain commands
Most commands can be combined to one call. Thats shorter than separate function calls in most cases. Here is an example to make the selected text bold:
```js
editor
.chain()
.focus()
.toggleBold()
.run()
```
The `.chain()` is required to start a new chain and the `.run()` is needed to actually execute all the commands in between.
In the example above two different commands are executed at once. When a user clicks on a button outside of the content, the editor isnt in focus anymore. Thats why you probably want to add a `.focus()` call to most of your commands. It brings back the focus to the editor, so the user can continue to type.
All chained commands are kind of queued up. They are combined to one single transaction. That means, the content is only updated once, also the `update` event is only triggered once.
:::warning Important
By default Prosemirror **does not support chaining** which means that you need to update the positions between chained commands via [**Transaction mapping**](https://prosemirror.net/docs/ref/#transform.Mapping).
:::
For example you want to chain a **delete** and **insert** command in one chain, you need to keep track of the position inside your chain commands. Here is an example:
```js
// here we add two custom commands to the editor to demonstrate transaction mapping between two transaction steps
addCommands() {
return {
delete: () => ({ tr }) => {
const { $from, $to } = tr.selection
// here we use tr.mapping.map to map the position between transaction steps
const from = tr.mapping.map($from.pos)
const to = tr.mapping.map($to.pos)
tr.delete(from, to)
return true
},
insert: (content: string) => ({ tr }) => {
const { $from } = tr.selection
// here we use tr.mapping.map to map the position between transaction steps
const pos = tr.mapping.map($from.pos)
tr.insertText(content, pos)
return true
},
}
}
```
Now you can do the following without `insert` inserting the content into the wrong position:
```js
editor.chain().delete().insert('foo').run()
```
#### Chaining inside custom commands
When chaining a command, the transaction is held back. If you want to chain commands inside your custom commands, youll need to use said transaction and add to it. Here is how you would do that:
```js
addCommands() {
return {
customCommand: attributes => ({ chain }) => {
// Doesnt work:
// return editor.chain() …
// Does work:
return chain()
.insertContent('foo!')
.insertContent('bar!')
.run()
},
}
}
```
### Inline commands
In some cases, its helpful to put some more logic in a command. Thats why you can execute commands in commands. I know, that sounds crazy, but lets look at an example:
```js
editor
.chain()
.focus()
.command(({ tr }) => {
// manipulate the transaction
tr.insertText('hey, thats cool!')
return true
})
.run()
```
### Dry run for commands
Sometimes, you dont want to actually run the commands, but only know if it would be possible to run commands, for example to show or hide buttons in a menu. Thats what we added `.can()` for. Everything coming after this method will be executed, without applying the changes to the document:
```js
editor
.can()
.toggleBold()
```
And you can use it together with `.chain()`, too. Here is an example which checks if its possible to apply all the commands:
```js
editor
.can()
.chain()
.toggleBold()
.toggleItalic()
.run()
```
Both calls would return `true` if its possible to apply the commands, and `false` in case its not.
In order to make that work with your custom commands, dont forget to return `true` or `false`.
For some of your own commands, you probably want to work with the raw [transaction](/api/introduction). To make them work with `.can()` you should check if the transaction should be dispatched. Here is how you can create a simple `.insertText()` command:
```js
export default (value) => ({ tr, dispatch }) => {
if (dispatch) {
tr.insertText(value)
}
return true
}
```
If youre just wrapping another Tiptap command, you dont need to check that, well do it for you.
```js
addCommands() {
return {
bold: () => ({ commands }) => {
return commands.toggleMark('bold')
},
}
}
```
If youre just wrapping a plain ProseMirror command, youll need to pass `dispatch` anyway. Then theres also no need to check it:
```js
import { exitCode } from '@tiptap/pm/commands'
export default () => ({ state, dispatch }) => {
return exitCode(state, dispatch)
}
```
### Try commands
If you want to run a list of commands, but want only the first successful command to be applied, you can do this with the `.first()` method. This method runs one command after the other and stops at the first which returns `true`.
For example, the backspace key tries to undo an input rule first. If that was successful, it stops there. If no input rule has been applied and thus cant be reverted, it runs the next command and deletes the selection, if there is one. Here is the simplified example:
```js
editor.first(({ commands }) => [
() => commands.undoInputRule(),
() => commands.deleteSelection(),
// …
])
```
Inside of commands you can do the same thing:
```js
export default () => ({ commands }) => {
return commands.first([
() => commands.undoInputRule(),
() => commands.deleteSelection(),
// …
])
}
```
## List of commands
Have a look at all of the core commands listed below. They should give you a good first impression of whats possible.
### Content
| Command | Description | Links |
| ------------------ | -------------------------------------------------------- | --------------------------------------- |
| clearContent() | Clear the whole document. | [More](/api/commands/clear-content) |
| insertContent() | Insert a node or string of HTML at the current position. | [More](/api/commands/insert-content) |
| insertContentAt() | Insert a node or string of HTML at a specific position. | [More](/api/commands/insert-content-at) |
| setContent() | Replace the whole document with new content. | [More](/api/commands/set-content) |
### Nodes & Marks
| Command | Description | Links |
| ----------------------- | --------------------------------------------------------- | ------------------------------------ |
| clearNodes() | Normalize nodes to a simple paragraph. | [More](/api/commands/clear-nodes) |
| createParagraphNear() | Create a paragraph nearby. | [More](/api/commands/create-paragraph-near) |
| deleteNode() | Delete a node. | [More](/api/commands/delete-node) |
| extendMarkRange() | Extends the text selection to the current mark. | [More](/api/commands/extend-mark-range) |
| exitCode() | Exit from a code block. | [More](/api/commands/exit-code) |
| joinBackward() | Join two nodes backward. | [More](/api/commands/join-backward) |
| joinForward() | Join two nodes forward. | [More](/api/commands/join-forward) |
| lift() | Removes an existing wrap. | [More](/api/commands/lift) |
| liftEmptyBlock() | Lift block if empty. | [More](/api/commands/lift-empty-block) |
| newlineInCode() | Add a newline character in code. | [More](/api/commands/newline-in-code) |
| resetAttributes() | Resets some node or mark attributes to the default value. | [More](/api/commands/reset-attributes) |
| setMark() | Add a mark with new attributes. | [More](/api/commands/set-mark) |
| setNode() | Replace a given range with a node. | [More](/api/commands/set-node) |
| splitBlock() | Forks a new node from an existing node. | [More](/api/commands/split-block) |
| toggleMark() | Toggle a mark on and off. | [More](/api/commands/toggle-mark) |
| toggleNode() | Toggle a node with another node. | [More](/api/commands/toggle-node) |
| toggleWrap() | Wraps nodes in another node, or removes an existing wrap. | [More](/api/commands/toggle-wrap) |
| undoInputRule() | Undo an input rule. | [More](/api/commands/undo-input-rule) |
| unsetAllMarks() | Remove all marks in the current selection. | [More](/api/commands/unset-all-marks) |
| unsetMark() | Remove a mark in the current selection. | [More](/api/commands/unset-mark) |
| updateAttributes() | Update attributes of a node or mark. | [More](/api/commands/update-attributes) |
### Lists
| Command | Description | Links |
| ---------------- | ------------------------------------------- | ------------------------------------ |
| liftListItem() | Lift the list item into a wrapping list. | [More](/api/commands/lift-list-item) |
| sinkListItem() | Sink the list item down into an inner list. | [More](/api/commands/sink-list-item) |
| splitListItem() | Splits one list item into two list items. | [More](/api/commands/split-list-item) |
| toggleList() | Toggle between different list types. | [More](/api/commands/toggle-list) |
| wrapInList() | Wrap a node in a list. | [More](/api/commands/wrap-in-list) |
### Selection
| Command | Description | Links |
| --------------------- | --------------------------------------- | ------------------------------------ |
| blur() | Removes focus from the editor. | [More](/api/commands/blur) |
| deleteRange() | Delete a given range. | [More](/api/commands/delete-range) |
| deleteSelection() | Delete the selection, if there is one. | [More](/api/commands/delete-selection) |
| enter() | Trigger enter. | [More](/api/commands/enter) |
| focus() | Focus the editor at the given position. | [More](/api/commands/focus) |
| keyboardShortcut() | Trigger a keyboard shortcut. | [More](/api/commands/keyboard-shortcut) |
| scrollIntoView() | Scroll the selection into view. | [More](/api/commands/scroll-into-view) |
| selectAll() | Select the whole document. | [More](/api/commands/select-all) |
| selectNodeBackward() | Select a node backward. | [More](/api/commands/select-node-backward) |
| selectNodeForward() | Select a node forward. | [More](/api/commands/select-node-forward) |
| selectParentNode() | Select the parent node. | [More](/api/commands/select-parent-node) |
| setNodeSelection() | Creates a NodeSelection. | [More](/api/commands/set-node-selection) |
| setTextSelection() | Creates a TextSelection. | [More](/api/commands/set-text-selection) |
<!-- ## Example use cases
### Quote a text
TODO
Add a blockquote, with a specified text, add a paragraph below, set the cursor there.
```js
// Untested, work in progress, likely to change
this.editor
.chain()
.focus()
.createParagraphNear()
.insertContent(text)
.setBlockquote()
.insertContent('<p></p>')
.createParagraphNear()
.unsetBlockquote()
.createParagraphNear()
.insertContent('<p></p>')
.run()
```
Add a custom command to insert a node.
```js
addCommands() {
return {
insertTimecode: attributes => ({ chain }) => {
return chain()
.focus()
.insertContent({
type: 'heading',
attrs: {
level: 2,
},
content: [
{
type: 'text',
text: 'heading',
},
],
})
.insertText(' ')
.run();
},
}
},
```
-->
## Write your own commands
All extensions can add additional commands (and most do), check out the specific [documentation for the provided nodes](/api/nodes), [marks](/api/marks), and [extensions](/api/extensions) to learn more about those. And of course, you can [add your custom extensions](/guide/custom-extensions) with custom commands aswell.
But how do you write those commands? Theres a little bit to learn about that.
:::pro Oops, this is work in progress
A well-written documentation needs attention to detail, a great understanding of the project and time to write.
Though Tiptap is used by thousands of developers all around the world, its still a side project for us. Lets change that and make open source our full-time job! With nearly 300 sponsors we are half way there already.
Join them and become a sponsor! Enable us to put more time into open source and well fill this page and keep it up to date for you.
[Become a sponsor on GitHub →](https://github.com/sponsors/ueberdosis)
:::

View File

@ -1,11 +0,0 @@
# blur
This command removes the focus from the editor.
See also: [focus](/api/commands/focus)
## Usage
```js
// Remove the focus from the editor
editor.commands.blur()
```

View File

@ -1,21 +0,0 @@
# clearContent
The `clearContent` command deletes the current document.
Keep in mind that the editor will enforce the configured schema, and the document wont be `null`. The default [`Document`](/api/nodes/document) expects to have at least one block node, which is the paragraph by default. In other words: Even after running that command the document will have at least one (empty) paragraph.
See also: [setContent](/api/commands/set-content), [insertContent](/api/commands/insert-content)
## Parameters
`emitUpdate: boolean (false)`
By default, it doesnt trigger the update event. Passing `true` doesnt prevent triggering the update event.
## Usage
```js
// Remove all content from the document
editor.commands.clearContent()
// Remove all content, and trigger the `update` event
editor.commands.clearContent(true)
```

View File

@ -1,10 +0,0 @@
# clearNodes
The `clearNodes` command normalizes nodes to the default node, which is the paragraph by default. Itll even normalize all kind of lists. For advanced use cases it can come in handy, before applying a new node type.
If you wonder how you can define the default node: It depends on whats in the `content` attribute of your [`Document`](/api/nodes/document), by default thats `block+` (at least one block node) and the [`Paragraph`](/api/nodes/paragraph) node has the highest priority, so its loaded first and is therefore the default node.
## Usage
```js
editor.commands.clearNodes()
```

View File

@ -1,7 +0,0 @@
# createParagraphNear
If a block node is currently selected, the `createParagraphNear` command creates an empty paragraph after the currently selected block node. If the selected block node is the first child of its parent, the new paragraph will be inserted before the current selection.
## Usage
```js
editor.commands.createParagraphNear()
```

View File

@ -1,16 +0,0 @@
# cut
This command cuts out content and places it into the given position.
See also: [focus](/api/commands/cut)
## Usage
```js
const from = editor.state.selection.from
const to = editor.state.selection.to
const endPos = editor.state.doc.nodeSize - 2
// Cut out content from range and put it at the end of the document
editor.commands.cut({ from, to }, endPos)
```

View File

@ -1,16 +0,0 @@
# deleteNode
The `deleteNode` command deletes a node inside the current selection. It requires a `typeOrName` argument, which can be a string or a `NodeType` to find the node that needs to be deleted. After deleting the node, the view will automatically scroll to the cursors position.
## Parameters
`typeOrName: string | NodeType`
## Usage
```js
// deletes a paragraph node
editor.commands.deleteNode('paragraph')
// or
// deletes a custom node
editor.commands.deleteNode(MyCustomNode)
```

View File

@ -1,10 +0,0 @@
# deleteRange
The `deleteRange` command deletes everything in a given range. It requires a `range` attribute of type `Range`.
## Parameters
`range: Range`
## Usage
```js
editor.commands.deleteRange({ from: 0, to: 12 })
```

View File

@ -1,7 +0,0 @@
# deleteSelection
The `deleteSelection` command deletes the currently selected nodes. If no selection exists, nothing will be deleted.
## Usage
```js
editor.commands.deleteSelection()
```

View File

@ -1,7 +0,0 @@
# enter
The `enter` command triggers an enter programmatically.
## Usage
```js
editor.commands.enter()
```

View File

@ -1,7 +0,0 @@
# exitCode
The `exitCode` command will create a default block after the current selection if the selection is a `code` element and move the cursor to the new block.
## Usage
```js
editor.commands.exitCode()
```

View File

@ -1,29 +0,0 @@
# extendMarkRange
The `extendMarkRange` command expands the current selection to encompass the current mark. If the current selection doesnt have the specified mark, nothing changes.
## Parameters
`typeOrName: string | MarkType`
Name or type of the mark.
`attributes?: Record<string, any>`
Optionally, you can specify attributes that the extented mark must contain.
## Usage
```js
// Expand selection to link marks
editor.commands.extendMarkRange('link')
// Expand selection to link marks with specific attributes
editor.commands.extendMarkRange('link', { href: 'https://google.com' })
// Expand selection to link mark and update attributes
editor
.chain()
.extendMarkRange('link')
.updateAttributes('link', {
href: 'https://duckduckgo.com'
})
.run()
```

View File

@ -1,33 +0,0 @@
# focus
This command sets the focus back to the editor.
When a user clicks on a button outside the editor, the browser sets the focus to that button. In most scenarios you want to focus the editor then again. Thats why youll see that in basically every demo here.
See also: [setTextSelection](/api/commands/set-text-selection), [blur](/api/commands/blur)
## Parameters
`position: 'start' | 'end' | 'all' | number | boolean | null (false)`
By default, its restoring the cursor position (and text selection). Pass a position to move the cursor to.
`options: { scrollIntoView: boolean }`
Defines whether to scroll to the cursor when focusing. Defaults to `true`.
## Usage
```js
// Set the focus to the editor
editor.commands.focus()
// Set the cursor to the first position
editor.commands.focus('start')
// Set the cursor to the last position
editor.commands.focus('end')
// Selects the whole document
editor.commands.focus('all')
// Set the cursor to position 10
editor.commands.focus(10)
```

View File

@ -1,20 +0,0 @@
# forEach
Loop through an array of items.
## Parameters
`items: any[]`
An array of items.
`fn: (item: any, props: CommandProps & { index: number }) => boolean`
A function to do anything with your item.
## Usage
```js
const items = ['foo', 'bar', 'baz']
editor.commands.forEach(items, (item, { commands }) => {
return commands.insertContent(item)
})
```

View File

@ -1,26 +0,0 @@
# insertContentAt
The `insertContentAt` will insert a string of html or a node at a given position or range. If a range is given, the new content will replace the content in the given range with the new content.
## Parameters
`position: number | Range`
The position or range the content will be inserted in.
`value: Content`
The content to be inserted. Can be a string of HTML or a node.
`options: Record<string, any>`
* updateSelection: controls if the selection should be moved to the newly inserted content.
* parseOptions: Passed content is parsed by ProseMirror. To hook into the parsing, you can pass `parseOptions` which are then handled by [ProseMirror](https://prosemirror.net/docs/ref/#model.ParseOptions).
## Usage
```js
editor.commands.insertContentAt(12, '<p>Hello world</p>', {
updateSelection: true,
parseOptions: {
preserveWhitespace: 'full',
}
})
```

View File

@ -1,63 +0,0 @@
# insertContent
The `insertContent` command adds the passed value to the document.
See also: [setContent](/api/commands/set-content), [clearContent](/api/commands/clear-content)
## Parameters
`value: Content`
The command is pretty flexible and takes plain text, HTML or even JSON as a value.
## Usage
```js
// Plain text
editor.commands.insertContent('Example Text')
// HTML
editor.commands.insertContent('<h1>Example Text</h1>')
// HTML with trim white space
editor.commands.insertContent('<h1>Example Text</h1>',
{
parseOptions: {
preserveWhitespace: false,
}
})
// JSON/Nodes
editor.commands.insertContent({
type: 'heading',
attrs: {
level: 1,
},
content: [
{
type: 'text',
text: 'Example Text',
},
],
})
// Multiple nodes at once
editor.commands.insertContent([
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'First paragraph',
},
],
},
{
type: 'paragraph',
content: [
{
type: 'text',
text: 'Second paragraph',
},
],
},
])
```

View File

@ -1,7 +0,0 @@
# joinBackward
The `joinBackward` command joins two nodes backwards from the current selection. If the selection is empty and at the start of a textblock, `joinBackward` will try to reduce the distance between that block and the block before it. [See also](https://prosemirror.net/docs/ref/#commands.joinBackward)
## Usage
```js
editor.commands.joinBackward()
```

View File

@ -1,8 +0,0 @@
# joinDown
The `joinDown` command joins the selected block, or if there is a text selection, the closest ancestor block of the selection that can be joined, with the sibling below it. [See also](https://prosemirror.net/docs/ref/#commands.joinDown)
## Usage
```js
editor.commands.joinDown()
```

View File

@ -1,8 +0,0 @@
# joinForward
The `joinForward` command joins two nodes forwards from the current selection. If the selection is empty and at the end of a textblock, `joinForward` will try to reduce the distance between that block and the block after it. [See also](https://prosemirror.net/docs/ref/#commands.joinForward)
## Usage
```js
editor.commands.joinForward()
```

View File

@ -1,8 +0,0 @@
# joinTextblockBackward
A more limited form of joinBackward that only tries to join the current textblock to the one before it, if the cursor is at the start of a textblock. [See also](https://prosemirror.net/docs/ref/#commands.joinTextblockBackward)
## Usage
```js
editor.commands.joinTextblockBackward()
```

View File

@ -1,8 +0,0 @@
# joinTextblockForward
A more limited form of joinForward that only tries to join the current textblock to the one after it, if the cursor is at the end of a textblock. [See also](https://prosemirror.net/docs/ref/#commands.joinTextblockForward)
## Usage
```js
editor.commands.joinTextblockForward()
```

View File

@ -1,8 +0,0 @@
# joinUp
The `joinUp` command joins the selected block, or if there is a text selection, the closest ancestor block of the selection that can be joined, with the sibling above it. [See also](https://prosemirror.net/docs/ref/#commands.joinUp)
## Usage
```js
editor.commands.joinUp()
```

View File

@ -1,12 +0,0 @@
# keyboardShortcut
The `keyboardShortcut` command will try to trigger a ShortcutEvent with a given name.
## Parameters
`name: String`
The name of the shortcut to trigger.
## Usage
```js
editor.commands.keyboardShortcut('undo')
```

View File

@ -1,7 +0,0 @@
# liftEmptyBlock
If the currently selected block is an empty textblock, lift it if possible. **Lifting** means, that the block will be moved to the parent of the block it is currently in.
## Usage
```js
editor.commands.liftEmptyBlock()
```

View File

@ -1,7 +0,0 @@
# liftListItem
The `liftListItem` will try to lift the list item around the current selection up into a wrapping parent list.
## Usage
```js
editor.commands.liftListItem()
```

View File

@ -1,20 +0,0 @@
# lift
The `lift` command lifts a given node up into it's parent node. **Lifting** means, that the block will be moved to the parent of the block it is currently in.
## Parameters
`typeOrName: String | NodeType`
The node that should be lifted. If the node is not found in the current selection, ignore the command.
`attributes: Record<string, any>`
The attributes the node should have to be lifted. This is **optional**.
## Usage
```js
// lift any headline
editor.commands.lift('headline')
// lift only h2
editor.commands.lift('headline', { level: 2 })
```

View File

@ -1,7 +0,0 @@
# newlineInCode
`newlineInCode` inserts a new line in the current code block. If a selection is set, the selection will be replaced with a newline character.
## Usage
```js
editor.commands.newlineInCode()
```

View File

@ -1,17 +0,0 @@
# resetAttributes
`resetAttributes` resets some of the nodes attributes back to it's default attributes.
## Parameters
`typeOrName: string | Node`
The node that should be resetted. Can be a string or a Node.
`attributes: string | string[]`
A string or an array of strings that defines which attributes should be reset.
## Usage
```js
// reset the style and class attributes on the currently selected paragraph nodes
editor.commands.resetAttributes('paragraph', ['style', 'class'])
```

View File

@ -1,7 +0,0 @@
# scrollIntoView
`scrollIntoView` scrolls the view to the current selection or cursor position.
## Usage
```js
editor.commands.scrollIntoView()
```

View File

@ -1,8 +0,0 @@
# selectAll
Selects the whole document at once.
## Usage
```js
// Select the whole document
editor.commands.selectAll()
```

View File

@ -1,7 +0,0 @@
# selectNodeBackward
If the selection is empty and at the start of a textblock, `selectNodeBackward` will select the node before the current textblock if possible.
## Usage
```js
editor.commands.selectNodeBackward()
```

View File

@ -1,7 +0,0 @@
# selectNodeForward
If the selection is empty and at the end of a textblock, `selectNodeForward` will select the node after the current textblock if possible.
## Usage
```js
editor.commands.selectNodeForward()
```

View File

@ -1,7 +0,0 @@
# selectParentNode
`selectParentNode` will try to get the parent node of the currently selected node and move the selection to that node.
## Usage
```js
editor.commands.selectParentNode()
```

View File

@ -1,7 +0,0 @@
# selectTextblockEnd
The `selectTextblockEnd` will move the cursor to the end of the current textblock if the block is a valid textblock.
## Usage
```js
editor.commands.selectTextblockEnd()
```

View File

@ -1,7 +0,0 @@
# selectTextblockStart
The `selectTextblockStart` will move the cursor to the start of the current textblock if the block is a valid textblock.
## Usage
```js
editor.commands.selectTextblockStart()
```

View File

@ -1,40 +0,0 @@
# setContent
The `setContent` command replaces the document with a new one. You can pass JSON or HTML, both work fine. Its basically the same as setting the `content` on initialization.
See also: [insertContent](/api/commands/insert-content), [clearContent](/api/commands/clear-content)
## Parameters
`content: string`
Pass a string (JSON or HTML) as [content](/guide/output). The editor will only render whats allowed according to the [schema](/api/schema).
`emitUpdate?: Boolean (false)`
By default, it doesnt trigger the update event. Passing `true` doesnt prevent triggering the update event.
`parseOptions?: Record<string, any>`
Options to configure the parsing can be passed during initialization and/or with setContent. Read more about parseOptions in the [ProseMirror documentation](https://prosemirror.net/docs/ref/#model.ParseOptions).
## Usage
```js
// HTML
editor.commands.setContent('<p>Example Text</p>')
// JSON
editor.commands.setContent({
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Example Text"
}
]
}
]
})
```

View File

@ -1,17 +0,0 @@
# setMark
The `setMark` command will add a new mark at the current selection.
## Parameters
`typeOrName: string | MarkType`
The type of a mark to add. Can be a string or a MarkType.
`attributes: Record<string, any>`
The attributes that should be applied to the mark. **This is optional.**
## Usage
```js
editor.commands.setMark("bold", { class: 'bold-tag' })
```

View File

@ -1,21 +0,0 @@
# setMeta
Store a metadata property in the current transaction.
## Parameters
`key: string`
The name of your metadata. You can get its value at any time with [getMeta](https://prosemirror.net/docs/ref/#state.Transaction.getMeta).
`value: any`
Store any value within your metadata.
## Usage
```js
// Prevent the update event from being triggered
editor.commands.setMeta('preventUpdate', true)
// Store any value in the current transaction.
// You can get this value at any time with tr.getMeta('foo').
editor.commands.setMeta('foo', 'bar')
```

View File

@ -1,12 +0,0 @@
# setNodeSelection
`setNodeSelection` creates a new NodeSelection at a given position. A node selection is a selection that points to a single node. [See more](https://prosemirror.net/docs/ref/#state.NodeSelection)
## Parameters
`position: number`
The position the NodeSelection will be created at.
## Usage
```js
editor.commands.setNodeSelection(10)
```

View File

@ -1,17 +0,0 @@
# setNode
The `setNode` command will replace a given range with a given node. The range depends on the current selection. **Important**: Currently `setNode` only supports text block nodes.
## Parameters
`typeOrName: string | NodeType`
The type of the node that will replace the range. Can be a string or a NodeType.
`attributes?: Record<string, any>`
The attributes that should be applied to the node. **This is optional.**
## Usage
```js
editor.commands.setNode("paragraph", { id: "paragraph-01" })
```

View File

@ -1,19 +0,0 @@
# setTextSelection
If you think of selection in the context of an editor, youll probably think of a text selection. With `setTextSelection` you can control that text selection and set it to a specified range or position.
See also: [focus](/api/commands/focus), [setNodeSelection](/api/commands/set-node-selection), [deleteSelection](/api/commands/delete-selection), [selectAll](/api/commands/select-all)
## Parameters
`position: number | Range`
Pass a number, or a Range, for example `{ from: 5, to: 10 }`.
## Usage
```js
// Set the cursor to the specified position
editor.commands.setTextSelection(10)
// Set the text selection to the specified range
editor.commands.setTextSelection({ from: 5, to: 10 })
```

View File

@ -1,7 +0,0 @@
# sinkListItem
The `sinkListItem` will try to sink the list item around the current selection down into a wrapping child list.
## Usage
```js
editor.commands.sinkListItem()
```

View File

@ -1,16 +0,0 @@
# splitBlock
`splitBlock` will split the current node into two nodes at the current [NodeSelection](https://prosemirror.net/docs/ref/#state.NodeSelection). If the current selection is not splittable, the command will be ignored.
## Parameters
`options: Record<string, any>`
* `keepMarks: boolean` - Defines if the marks should be kept or removed. Defaults to `true`.
## Usage
```js
// split the current node and keep marks
editor.commands.splitBlock()
// split the current node and don't keep marks
editor.commands.splitBlock({ keepMarks: false })
```

View File

@ -1,12 +0,0 @@
# splitListItem
`splitListItem` splits one list item into two separate list items. If this is a nested list, the wrapping list item should be split.
## Parameters
`typeOrName: string | NodeType`
The type of node that should be split into two separate list items.
## Usage
```js
editor.commands.splitListItem('bullet_list')
```

View File

@ -1,28 +0,0 @@
# toggleList
`toggleList` will toggle between different types of lists.
## Parameters
`listTypeOrName: string | NodeType`
The type of node that should be used for the wrapping list
`itemTypeOrName: string | NodeType`
The type of node that should be used for the list items
`keepMarks?: boolean`
If marks should be kept as list items or not
`attributes?: Record<string, any>`
The attributes that should be applied to the list. **This is optional.**
## Usage
```js
// toggle a bullet list with list items
editor.commands.toggleList('bullet_list', 'list_item')
// toggle a numbered list with list items
editor.commands.toggleList('ordered_list', 'list_item')
```

View File

@ -1,26 +0,0 @@
# toggleMark
The `toggleMark` command toggles a specific mark on and off at the current selection.
## Parameters
`typeOrName: string | MarkType`
The type of mark that should be toggled.
`attributes?: Record<string, any>`
The attributes that should be applied to the mark. **This is optional.**
`options?: Record<string, any>`
* `extendEmptyMarkRange: boolean` - Removes the mark even across the current selection. Defaults to `false`
## Usage
```js
// toggles a bold mark
editor.commands.toggleMark('bold')
// toggles bold mark with a color attribute
editor.commands.toggleMark('bold', { color: 'red' })
// toggles a bold mark with a color attribute and removes the mark across the current selection
editor.commands.toggleMark('bold', { color: 'red' }, { extendEmptyMarkRange: true })
```

View File

@ -1,24 +0,0 @@
# toggleNode
`toggleNode` will toggle a node with another node.
## Parameters
`typeOrName: string | NodeType`
The type of node that should be toggled.
`toggleTypeOrName: string | NodeType`
The type of node that should be used for the toggling.
`attributes?: Record<string, any>`
The attributes that should be applied to the node. **This is optional.**
## Usage
```js
// toggle a paragraph with a heading node
editor.commands.toggleNode('paragraph', 'heading', { level: 1 })
// toggle a paragraph with a image node
editor.commands.toggleNode('paragraph', 'image', { src: 'https://example.com/image.png' })
```

View File

@ -1,17 +0,0 @@
# toggleWrap
`toggleWrap` wraps the current node with a new node or removes a wrapping node.
## Parameters
`typeOrName: string | NodeType`
The type of node that should be used for the wrapping node.
`attributes?: Record<string, any>`
The attributes that should be applied to the node. **This is optional.**
## Usage
```js
// toggle wrap the current selection with a heading node
editor.commands.toggleWrap('heading', { level: 1 })
```

View File

@ -1,7 +0,0 @@
# undoInputRule
`undoInputRule` will undo the most recent input rule that was triggered.
## Usage
```js
editor.commands.undoInputRule()
```

View File

@ -1,7 +0,0 @@
# unsetAllMarks
`unsetAllMarks` will remove all marks from the current selection.
## Usage
```js
editor.commands.unsetAllMarks()
```

View File

@ -1,20 +0,0 @@
# unsetMark
`unsetMark` will remove the mark from the current selection. Can also remove all marks across the current selection.
## Parameters
`typeOrName: string | MarkType`
The type of mark that should be removed.
`options?: Record<string, any>`
* `extendEmptyMarkRange?: boolean` - Removes the mark even across the current selection. Defaults to `false`
## Usage
```js
// removes a bold mark
editor.commands.unsetMark('bold')
// removes a bold mark across the current selection
editor.commands.unsetMark('bold', { extendEmptyMarkRange: true })
```

View File

@ -1,23 +0,0 @@
# updateAttributes
The `updateAttributes` command sets attributes of a node or mark to new values. Not passed attributes wont be touched.
See also: [extendMarkRange](/api/commands/extend-mark-range)
## Parameters
`typeOrName: string | NodeType | MarkType`
Pass the type you want to update, for example `'heading'`.
`attributes: Record<string, any>`
This expects an object with the attributes that need to be updated. It doesnt need to have all attributes.
## Usage
```js
// Update node attributes
editor.commands.updateAttributes('heading', { level: 1 })
// Update mark attributes
editor.commands.updateAttributes('highlight', { color: 'pink' })
```

View File

@ -1,17 +0,0 @@
# wrapInList
`wrapInList` will wrap a node in the current selection in a list.
## Parameters
`typeOrName: string | NodeType`
The type of node that should be wrapped in a list.
`attributes?: Record<string, any>`
The attributes that should be applied to the list. **This is optional.**
## Usage
```js
// wrap a paragraph in a bullet list
editor.commands.wrapInList('paragraph')
```

View File

@ -1,419 +0,0 @@
---
tableOfContents: true
---
# Editor
## Introduction
This class is a central building block of Tiptap. It does most of the heavy lifting of creating a working [ProseMirror](https://ProseMirror.net/) editor such as creating the [`EditorView`](https://ProseMirror.net/docs/ref/#view.EditorView), setting the initial [`EditorState`](https://ProseMirror.net/docs/ref/#state.Editor_State) and so on.
## Methods
The editor instance will provide a bunch of public methods. Methods are regular functions and can return anything. Theyll help you to work with the editor.
Dont confuse methods with [commands](/api/commands). Commands are used to change the state of editor (content, selection, and so on) and only return `true` or `false`.
### can()
Check if a command or a command chain can be executed without actually executing it. Can be very helpful to enable/disable or show/hide buttons.
```js
// Returns `true` if the undo command can be executed
editor.can().undo()
```
### chain()
Create a command chain to call multiple commands at once.
```js
// Execute two commands at once
editor.chain().toggleBold().focus().run()
```
### destroy()
Stops the editor instance and unbinds all events.
```js
// Hasta la vista, baby!
editor.destroy()
```
### getHTML()
Returns the current editor document as HTML
```js
editor.getHTML()
```
### getJSON()
Returns the current editor document as JSON.
```js
editor.getJSON()
```
### getText()
Returns the current editor document as plain text.
| Parameter | Type | Description |
| ---------- | ------------------------------ | ------------------------ |
| options | { blockSeparator?: string, textSerializers?: Record<string, TextSerializer>} | Options for the serialization. |
```js
// Give me plain text!
editor.getText()
// Add two line breaks between nodes
editor.getText({ blockSeparator: "\n\n" })
```
### getAttributes()
Get attributes of the currently selected node or mark.
| Parameter | Type | Description |
| ---------- | ------------------------------ | ------------------------ |
| typeOrName | string \| NodeType \| MarkType | Name of the node or mark |
```js
editor.getAttributes('link').href
```
### isActive()
Returns if the currently selected node or mark is active.
| Parameter | Type | Description |
| ---------------------- | ------------------- | ------------------------------ |
| name | string \| null | Name of the node or mark |
| attributes | Record<string, any> | Attributes of the node or mark |
```js
// Check if its a heading
editor.isActive('heading')
// Check if its a heading with a specific attribute value
editor.isActive('heading', { level: 2 })
// Check if it has a specific attribute value, doesnt care what node/mark it is
editor.isActive({ textAlign: 'justify' })
```
### registerPlugin()
Register a ProseMirror plugin.
| Parameter | Type | Description |
| -------------- | -------------------------------------------------- | --------------------------------------------------------- |
| plugin | Plugin | A ProseMirror plugin |
| handlePlugins? | (newPlugin: Plugin, plugins: Plugin[]) => Plugin[] | Control how to merge the plugin into the existing plugins |
### setOptions()
Update editor options.
| Parameter | Type | Description |
| --------- | ---------------------- | ----------------- |
| options | Partial<EditorOptions> | A list of options |
```js
// Add a class to an existing editor instance
editor.setOptions({
editorProps: {
attributes: {
class: 'my-custom-class',
},
},
})
```
### setEditable()
Update editable state of the editor.
| Parameter | Type | Description |
| --------- | ------- | ------------------------------------------------------------- |
| editable | boolean | `true` when the user should be able to write into the editor. |
| emitUpdate | boolean | Defaults to `true`. Determines whether `onUpdate` is triggered. |
```js
// Make the editor read-only
editor.setEditable(false)
```
### unregisterPlugin()
Unregister a ProseMirror plugin.
| Parameter | Type | Description |
| --------------- | ------------------- | ---------------- |
| nameOrPluginKey | string \| PluginKey | The plugins name |
## Getters
### isEditable
Returns whether the editor is editable or read-only.
```js
editor.isEditable
```
### isEmpty
Check if there is content.
```js
editor.isEmpty
```
### isFocused
Check if the editor is focused.
```js
editor.isFocused
```
### isDestroyed
Check if the editor is destroyed.
```js
editor.isDestroyed
```
### isCapturingTransaction
Check if the editor is capturing a transaction.
```js
editor.isCapturingTransaction
```
## Settings
### element
The `element` specifies the HTML element the editor will be binded to. The following code will integrate Tiptap with an element with the `.element` class:
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
element: document.querySelector('.element'),
extensions: [
StarterKit,
],
})
```
You can even initiate your editor before mounting it to an element. This is useful when your DOM is not yet available. Just leave out the `element`, well create one for you. Append it to your container at a later date:
```js
yourContainerElement.append(editor.options.element)
```
### extensions
Its required to pass a list of extensions to the `extensions` property, even if you only want to allow paragraphs.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import Highlight from '@tiptap/extension-highlight'
new Editor({
// Use the default extensions
extensions: [
StarterKit,
],
// … or use specific extensions
extensions: [
Document,
Paragraph,
Text,
],
// … or both
extensions: [
StarterKit,
Highlight,
],
})
```
### content
With the `content` property you can provide the initial content for the editor. This can be HTML or JSON.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
content: `<p>Example Text</p>`,
extensions: [
StarterKit,
],
})
```
### editable
The `editable` property determines if users can write into the editor.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
content: `<p>Example Text</p>`,
extensions: [
StarterKit,
],
editable: false,
})
```
### autofocus
With `autofocus` you can force the cursor to jump in the editor on initialization.
| Value | Description |
| --------- | ------------------------------------------------------ |
| `'start'` | Sets the focus to the beginning of the document. |
| `'end'` | Sets the focus to the end of the document. |
| `'all'` | Selects the whole document. |
| `Number` | Sets the focus to a specific position in the document. |
| `true` | Enables autofocus. |
| `false` | Disables autofocus. |
| `null` | Disables autofocus. |
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
extensions: [
StarterKit,
],
autofocus: false,
})
```
### enableInputRules
By default, Tiptap enables all [input rules](/guide/custom-extensions/#input-rules). With `enableInputRules` you can control that.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
content: `<p>Example Text</p>`,
extensions: [
StarterKit,
],
enableInputRules: false,
})
```
Alternatively you can allow only specific input rules.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import Link from '@tiptap/extension-link'
new Editor({
content: `<p>Example Text</p>`,
extensions: [
StarterKit,
Link,
],
// pass an array of extensions or extension names
// to allow only specific input rules
enableInputRules: [Link, 'horizontalRule'],
})
```
### enablePasteRules
By default, Tiptap enables all [paste rules](/guide/custom-extensions/#paste-rules). With `enablePasteRules` you can control that.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
content: `<p>Example Text</p>`,
extensions: [
StarterKit,
],
enablePasteRules: false,
})
```
Alternatively you can allow only specific paste rules.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import Link from '@tiptap/extension-link'
new Editor({
content: `<p>Example Text</p>`,
extensions: [
StarterKit,
Link,
],
// pass an array of extensions or extension names
// to allow only specific paste rules
enablePasteRules: [Link, 'horizontalRule'],
})
```
### injectCSS
By default, Tiptap injects [a little bit of CSS](https://github.com/ueberdosis/tiptap/tree/main/packages/core/src/style.ts). With `injectCSS` you can disable that.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
extensions: [
StarterKit,
],
injectCSS: false,
})
```
### injectNonce
When you use a [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) with `nonce`, you can specify a `nonce` to be added to dynamically created elements. Here is an example:
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
new Editor({
extensions: [
StarterKit,
],
injectCSS: true,
injectNonce: "your-nonce-here"
})
```
### editorProps
For advanced use cases, you can pass `editorProps` which will be handled by [ProseMirror](https://prosemirror.net/docs/ref/#view.EditorProps). You can use it to override various editor events or change editor DOM element attributes, for example to add some Tailwind classes. Here is an example:
```js
new Editor({
// Learn more: https://prosemirror.net/docs/ref/#view.EditorProps
editorProps: {
attributes: {
class: 'prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto focus:outline-none',
},
transformPastedText(text) {
return text.toUpperCase()
}
}
})
```
You can use that to hook into event handlers and pass - for example - a custom paste handler, too.
### parseOptions
Passed content is parsed by ProseMirror. To hook into the parsing, you can pass `parseOptions` which are then handled by [ProseMirror](https://prosemirror.net/docs/ref/#model.ParseOptions).
```js
new Editor({
// Learn more: https://prosemirror.net/docs/ref/#model.ParseOptions
parseOptions: {
preserveWhitespace: 'full',
},
})
```

View File

@ -1,169 +0,0 @@
---
tableOfContents: true
---
# Events
## Introduction
The editor fires a few different events that you can hook into. Lets have a look at all the available events first.
## List of available events
### beforeCreate
Before the view is created.
### create
The editor is ready.
### update
The content has changed.
### selectionUpdate
The selection has changed.
### transaction
The editor state has changed.
### focus
The editor is focused.
### blur
The editor isnt focused anymore.
### destroy
The editor is being destroyed.
### contentError
The content does not match the schema.
## Register event listeners
There are three ways to register event listeners.
### Option 1: Configuration
You can define your event listeners on a new editor instance right-away:
```js
const editor = new Editor({
onBeforeCreate({ editor }) {
// Before the view is created.
},
onCreate({ editor }) {
// The editor is ready.
},
onUpdate({ editor }) {
// The content has changed.
},
onSelectionUpdate({ editor }) {
// The selection has changed.
},
onTransaction({ editor, transaction }) {
// The editor state has changed.
},
onFocus({ editor, event }) {
// The editor is focused.
},
onBlur({ editor, event }) {
// The editor isnt focused anymore.
},
onDestroy() {
// The editor is being destroyed.
},
onContentError({ editor, error, disableCollaboration }) {
// The editor content does not match the schema.
},
})
```
### Option 2: Binding
Or you can register your event listeners on a running editor instance:
#### Bind event listeners
```js
editor.on('beforeCreate', ({ editor }) => {
// Before the view is created.
})
editor.on('create', ({ editor }) => {
// The editor is ready.
})
editor.on('update', ({ editor }) => {
// The content has changed.
})
editor.on('selectionUpdate', ({ editor }) => {
// The selection has changed.
})
editor.on('transaction', ({ editor, transaction }) => {
// The editor state has changed.
})
editor.on('focus', ({ editor, event }) => {
// The editor is focused.
})
editor.on('blur', ({ editor, event }) => {
// The editor isnt focused anymore.
})
editor.on('destroy', () => {
// The editor is being destroyed.
})
editor.on('contentError', ({ editor, error, disableCollaboration }) => {
// The editor content does not match the schema.
})
```
#### Unbind event listeners
If you need to unbind those event listeners at some point, you should register your event listeners with `.on()` and unbind them with `.off()` then.
```js
const onUpdate = () => {
// The content has changed.
}
// Bind …
editor.on('update', onUpdate)
// … and unbind.
editor.off('update', onUpdate)
```
### Option 3: Extensions
Moving your event listeners to custom extensions (or nodes, or marks) is also possible. Heres how that would look like:
```js
import { Extension } from '@tiptap/core'
const CustomExtension = Extension.create({
onBeforeCreate({ editor }) {
// Before the view is created.
},
onCreate({ editor }) {
// The editor is ready.
},
onUpdate({ editor }) {
// The content has changed.
},
onSelectionUpdate({ editor }) {
// The selection has changed.
},
onTransaction({ editor, transaction }) {
// The editor state has changed.
},
onFocus({ editor, event }) {
// The editor is focused.
},
onBlur({ editor, event }) {
// The editor isnt focused anymore.
},
onDestroy() {
// The editor is being destroyed.
},
onContentError({ editor, error, disableCollaboration }) {
// The editor content does not match the schema.
},
})
```

View File

@ -1,74 +0,0 @@
---
tableOfContents: true
---
# Extensions
## Introduction
Extensions add new capabilities to Tiptap and youll read the word extension here very often. Actually, there are literal Extensions. Those cant add to the schema, but can add functionality or change the behaviour of the editor.
There are also some extensions with more capabilities. We call them [nodes](/api/nodes) and [marks](/api/marks) which can render content in the editor.
## List of provided extensions
| Title | StarterKit ([view](/api/extensions/starter-kit)) | Source Code |
| ----------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| [BubbleMenu](/api/extensions/bubble-menu) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-bubble-menu/) |
| [CharacterCount](/api/extensions/character-count) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-character-count/) |
| [Collaboration](/api/extensions/collaboration) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-collaboration/) |
| [CollaborationCursor](/api/extensions/collaboration-cursor) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-collaboration-cursor/) |
| [Color](/api/extensions/color) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-color/) |
| [Dropcursor](/api/extensions/dropcursor) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-dropcursor/) |
| [FloatingMenu](/api/extensions/floating-menu) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-floating-menu/) |
| [Focus](/api/extensions/focus) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-focus/) |
| [FontFamily](/api/extensions/font-family) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-font-family/) |
| [Gapcursor](/api/extensions/gapcursor) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-gapcursor/) |
| [History](/api/extensions/history) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-history/) |
| [InvisibleCharacters](/api/extensions/invisible-characters) | | Requires a Tiptap Pro subscription |
| [Mathematics](/api/extensions/mathematics) | | Requires a Tiptap Pro subscription |
| [Placeholder](/api/extensions/placeholder) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-placeholder/) |
| [StarterKit](/api/extensions/starter-kit) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/starter-kit/) |
| [TextAlign](/api/extensions/text-align) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-text-align/) |
| [Typography](/api/extensions/typography) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-typography/) |
| [UniqueID](/api/extensions/unique-id) | | Requires a Tiptap Pro subscription |
You dont have to use it, but we prepared a `@tiptap/starter-kit` which includes the most common extensions. Read more about [`StarterKit`](/guide/configuration#default-extensions).
Also a list of community extensions can be found in the [Awesome Tiptap Repository](https://github.com/ueberdosis/awesome-tiptap#community-extensions). There is also a [Discussion Thread](https://github.com/ueberdosis/tiptap/discussions/2973) about community extensions.
## How extensions work
Although Tiptap tries to hide most of the complexity of ProseMirror, its built on top of its APIs and we recommend you to read through the [ProseMirror Guide](https://ProseMirror.net/docs/guide/) for advanced usage. Youll have a better understanding of how everything works under the hood and get more familiar with many terms and jargon used by Tiptap.
Existing [nodes](/api/nodes), [marks](/api/marks) and [extensions](/api/extensions) can give you a good impression on how to approach your own extensions. To make it easier to switch between the documentation and the source code, we linked to the file on GitHub from every single extension documentation page.
We recommend to start with customizing existing extensions first, and create your own extensions with the gained knowledge later. Thats why all the examples below extend existing extensions, but all examples will work on newly created extensions aswell.
## Create a new extension
Youre free to create your own extensions for Tiptap. Here is the boilerplate code thats needed to create and register your own extension:
```js
import { Extension } from '@tiptap/core'
const CustomExtension = Extension.create({
// Your code here
})
const editor = new Editor({
extensions: [
// Register your custom extension with the editor.
CustomExtension,
// … and dont forget all other extensions.
Document,
Paragraph,
Text,
// …
],
})
```
You can easily bootstrap a new extension via our CLI.
```bash
npm init tiptap-extension
```
Learn [more about custom extensions in our guide](/guide/custom-extensions).

View File

@ -1,129 +0,0 @@
---
description: Add a toolbar that pops up above the text. Great to apply inline formatting.
icon: chat-2-line
---
# Bubble Menu
[![Version](https://img.shields.io/npm/v/@tiptap/extension-bubble-menu.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-bubble-menu)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-bubble-menu.svg)](https://npmcharts.com/compare/@tiptap/extension-bubble-menu?minimal=true)
This extension will make a contextual menu appear near a selection of text. Use it to let users apply [marks](/api/marks) to their text selection.
As always, the markup and styling is totally up to you.
## Installation
```bash
npm install @tiptap/extension-bubble-menu
```
## Settings
### element
The DOM element that contains your menu.
Type: `HTMLElement`
Default: `null`
### updateDelay
The `BubbleMenu` debounces the `update` method to allow the bubble menu to not be updated on every selection update. This can be controlled in milliseconds.
The BubbleMenuPlugin will come with a default delay of 250ms. This can be deactivated, by setting the delay to `0` which deactivates the debounce.
Type: `Number`
Default: `undefined`
### tippyOptions
Under the hood, the `BubbleMenu` uses [tippy.js](https://atomiks.github.io/tippyjs/v6/all-props/). You can directly pass options to it.
Type: `Object`
Default: `{}`
### pluginKey
The key for the underlying ProseMirror plugin. Make sure to use different keys if you add more than one instance.
Type: `string | PluginKey`
Default: `'bubbleMenu'`
### shouldShow
A callback to control whether the menu should be shown or not.
Type: `(props) => boolean`
## Source code
[packages/extension-bubble-menu/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-bubble-menu/)
## Usage
### JavaScript
```js
import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'
new Editor({
extensions: [
BubbleMenu.configure({
element: document.querySelector('.menu'),
}),
],
})
```
### Frameworks
https://embed.tiptap.dev/preview/Extensions/BubbleMenu
### Custom logic
Customize the logic for showing the menu with the `shouldShow` option. For components, `shouldShow` can be passed as a prop.
```js
BubbleMenu.configure({
shouldShow: ({ editor, view, state, oldState, from, to }) => {
// only show the bubble menu for images and links
return editor.isActive('image') || editor.isActive('link')
},
})
```
### Multiple menus
Use multiple menus by setting an unique `pluginKey`.
```js
import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'
new Editor({
extensions: [
BubbleMenu.configure({
pluginKey: 'bubbleMenuOne',
element: document.querySelector('.menu-one'),
}),
BubbleMenu.configure({
pluginKey: 'bubbleMenuTwo',
element: document.querySelector('.menu-two'),
}),
],
})
```
Alternatively you can pass a ProseMirror `PluginKey`.
```js
import { Editor } from '@tiptap/core'
import BubbleMenu from '@tiptap/extension-bubble-menu'
import { PluginKey } from '@tiptap/pm/state'
new Editor({
extensions: [
BubbleMenu.configure({
pluginKey: new PluginKey('bubbleMenuOne'),
element: document.querySelector('.menu-one'),
}),
BubbleMenu.configure({
pluginKey: new PluginKey('bubbleMenuTwo'),
element: document.querySelector('.menu-two'),
}),
],
})
```

View File

@ -1,72 +0,0 @@
---
description: Limit the number of characters in your editor, or at least count them.
icon: calculator-line
---
# CharacterCount
[![Version](https://img.shields.io/npm/v/@tiptap/extension-character-count.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-character-count)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-character-count.svg)](https://npmcharts.com/compare/@tiptap/extension-character-count?minimal=true)
The `CharacterCount` extension limits the number of allowed characters to a specific length and is able to return the number of characters and words. Thats it, thats all.
## Installation
```bash
npm install @tiptap/extension-character-count
```
## Settings
### limit
The maximum number of characters that should be allowed.
Default: `null`
```js
CharacterCount.configure({
limit: 240,
})
```
### mode
The mode by which the size is calculated.
Default: `'textSize'`
```js
CharacterCount.configure({
mode: 'nodeSize',
})
```
## Storage
### characters()
Get the number of characters for the current document.
```js
editor.storage.characterCount.characters()
// Get the size of a specific node.
editor.storage.characterCount.characters({ node: someCustomNode })
// Overwrite the default `mode`.
editor.storage.characterCount.characters({ mode: 'nodeSize' })
```
### words()
Get the number of words for the current document.
```js
editor.storage.characterCount.words()
// Get the number of words for a specific node.
editor.storage.characterCount.words({ node: someCustomNode })
```
## Source code
[packages/extension-character-count/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-character-count/)
## Usage
https://embed.tiptap.dev/preview/Extensions/CharacterCount

View File

@ -1,62 +0,0 @@
---
description: See other users cursors and their name while they type.
icon: account-pin-circle-line
---
# CollaborationCursor
[![Version](https://img.shields.io/npm/v/@tiptap/extension-collaboration-cursor.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-collaboration-cursor)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-collaboration-cursor.svg)](https://npmcharts.com/compare/@tiptap/extension-collaboration-cursor?minimal=true)
This extension adds information about all connected users (like their name and a specified color), their current cursor position and their text selection (if theres one).
Open this page in multiple browser windows to test it.
## Installation
```bash
npm install @tiptap/extension-collaboration-cursor
```
This extension requires the [`Collaboration`](/api/extensions/collaboration) extension.
## Settings
### provider
A Y.js network provider, for example a [y-websocket](https://github.com/yjs/y-websocket) instance.
Default: `null`
### user
Attributes of the current user, assumes to have a name and a color, but can be used with any attribute. The values are synced with all other connected clients.
Default: `{ user: null, color: null }`
### render
A render function for the cursor, look at [the extension source code](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-collaboration-cursor/) for an example.
### selectionRender
A render function for the selection, look at [the extension source code](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-collaboration-cursor/) for an example.
## Commands
### updateUser()
Pass an object with updated attributes of the current user. It expects a `name` and a `color`, but you can add additional fields, too.
```js
editor.commands.updateUser({
name: 'John Doe',
color: '#000000',
avatar: 'https://unavatar.io/github/ueberdosis',
})
```
## Source code
[packages/extension-collaboration-cursor/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-collaboration-cursor/)
## Usage
:::warning Public
The content of this editor is shared with other users.
:::
https://embed.tiptap.dev/preview/Extensions/CollaborationCursor?hideSource
https://embed.tiptap.dev/preview/Extensions/CollaborationCursor
!!tiptap-collab-cta

View File

@ -1,87 +0,0 @@
---
description: Collaborative text editing can be fricking complex, but it doesnt have to be that way.
icon: user-voice-line
---
# Collaboration
[![Version](https://img.shields.io/npm/v/@tiptap/extension-collaboration.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-collaboration)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-collaboration.svg)](https://npmcharts.com/compare/@tiptap/extension-collaboration?minimal=true)
The Collaboration extension enables you to collaborate with others in a single document. The implementation is based on [Y.js by Kevin Jahns](https://github.com/yjs/yjs), which is the coolest thing to [integrate collaborative editing](/guide/collaborative-editing) in your project.
The history works totally different in a collaborative editing setup. If you undo a change, you dont want to undo changes of other users. To handle that behaviour this extension provides an own `undo` and `redo` command. Dont load the default [`History`](/api/extensions/history) extension together with the Collaboration extension to avoid conflicts.
## Installation
```bash
npm install @tiptap/extension-collaboration yjs y-websocket y-prosemirror
```
## Settings
### document
An initialized Y.js document.
Default: `null`
```js
Collaboration.configure({
document: new Y.Doc(),
})
```
### field
Name of a Y.js fragment, can be changed to sync multiple fields with one Y.js document.
Default: `'default'`
```js
Collaboration.configure({
document: new Y.Doc(),
field: 'title',
})
```
### fragment
A raw Y.js fragment, can be used instead of `document` and `field`.
Default: `null`
```js
Collaboration.configure({
fragment: new Y.Doc().getXmlFragment('body'),
})
```
## Commands
The `Collaboration` extension comes with its own history extension. Make sure to disable the default extension, if youre working with the `StarterKit`.
### undo()
Undo the last change.
```js
editor.commands.undo()
```
### redo()
Redo the last change.
```js
editor.commands.redo()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ------- | ----------------------------------------------------- | --------------------------------------------- |
| undo() | `Control`&nbsp;`Z` | `Cmd`&nbsp;`Z` |
| redo() | `Shift`&nbsp;`Control`&nbsp;`Z`<br>`Control`&nbsp;`Y` | `Shift`&nbsp;`Cmd`&nbsp;`Z`<br>`Cmd`&nbsp;`Y` |
## Source code
[packages/extension-collaboration/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-collaboration/)
## Usage
:::warning Public
The content of this editor is shared with other users.
:::
https://embed.tiptap.dev/preview/Extensions/Collaboration?hideSource
https://embed.tiptap.dev/preview/Extensions/Collaboration
!!tiptap-collab-cta

View File

@ -1,52 +0,0 @@
---
description: Add text color support to your editor (comes with unlimited colors).
icon: paint-brush-line
---
# Color
[![Version](https://img.shields.io/npm/v/@tiptap/extension-color.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-color)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-color.svg)](https://npmcharts.com/compare/@tiptap/extension-color?minimal=true)
This extension enables you to set the font color in the editor. It uses the [`TextStyle`](/api/marks/text-style) mark, which renders a `<span>` tag (and only that). The font color is applied as inline style then, for example `<span style="color: #958DF1">`.
## Installation
```bash
npm install @tiptap/extension-text-style @tiptap/extension-color
```
This extension requires the [`TextStyle`](/api/marks/text-style) mark.
## Settings
### types
A list of marks to which the color attribute should be applied to.
Default: `['textStyle']`
```js
Color.configure({
types: ['textStyle'],
})
```
## Commands
### setColor()
Applies the given font color as inline style.
```js
editor.commands.setColor('#ff0000')
```
### unsetColor()
Removes any font color.
```js
editor.commands.unsetColor()
```
## Source code
[packages/extension-color/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-color/)
## Usage
https://embed.tiptap.dev/preview/Extensions/Color

View File

@ -1,63 +0,0 @@
---
description: Adds a cursor when something is dragged inside the editor.
icon: drag-drop-line
---
# Dropcursor
[![Version](https://img.shields.io/npm/v/@tiptap/extension-dropcursor.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-dropcursor)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-dropcursor.svg)](https://npmcharts.com/compare/@tiptap/extension-dropcursor?minimal=true)
This extension loads the [ProseMirror Dropcursor plugin](https://github.com/ProseMirror/prosemirror-dropcursor) by Marijn Haverbeke, which shows a cursor at the drop position when something is dragged into the editor.
Note that Tiptap is headless, but the dropcursor needs CSS for its appearance. There are settings for the color and width, and youre free to add a custom CSS class.
## Installation
```bash
npm install @tiptap/extension-dropcursor
```
## Settings
### color
Color of the dropcursor.
Default: `'currentColor'`
```js
Dropcursor.configure({
color: '#ff0000',
})
```
### width
Width of the dropcursor.
Default: `1`
```js
Dropcursor.configure({
width: 2,
})
```
### class
One or multiple CSS classes that should be applied to the dropcursor.
```js
Dropcursor.configure({
class: 'my-custom-class',
})
```
## Source code
[packages/extension-dropcursor/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-dropcursor/)
## Usage
https://embed.tiptap.dev/preview/Extensions/Dropcursor

View File

@ -1,117 +0,0 @@
---
description: Make a toolbar appear automagically on empty lines.
icon: menu-4-line
---
# Floating Menu
[![Version](https://img.shields.io/npm/v/@tiptap/extension-floating-menu.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-floating-menu)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-floating-menu.svg)](https://npmcharts.com/compare/@tiptap/extension-floating-menu?minimal=true)
This extension will make a menu appear in an empty line.
## Installation
```bash
npm install @tiptap/extension-floating-menu
```
## Settings
### element
The DOM element that contains your menu.
Type: `HTMLElement`
Default: `null`
### tippyOptions
Under the hood, the `FloatingMenu` uses [tippy.js](https://atomiks.github.io/tippyjs/v6/all-props/). You can directly pass options to it.
Type: `Object`
Default: `{}`
### pluginKey
The key for the underlying ProseMirror plugin. Make sure to use different keys if you add more than one instance.
Type: `string | PluginKey`
Default: `'floatingMenu'`
### shouldShow
A callback to control whether the menu should be shown or not.
Type: `(props) => boolean`
## Source code
[packages/extension-floating-menu/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-floating-menu/)
## Using Vanilla JavaScript
```js
import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'
new Editor({
extensions: [
FloatingMenu.configure({
element: document.querySelector('.menu'),
}),
],
})
```
## Using a framework
https://embed.tiptap.dev/preview/Extensions/FloatingMenu
### Custom logic
Customize the logic for showing the menu with the `shouldShow` option. For components, `shouldShow` can be passed as a prop.
```js
FloatingMenu.configure({
shouldShow: ({ editor, view, state, oldState }) => {
// show the floating within any paragraph
return editor.isActive('paragraph')
},
})
```
### Multiple menus
Use multiple menus by setting an unique `pluginKey`.
```js
import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'
new Editor({
extensions: [
FloatingMenu.configure({
pluginKey: 'floatingMenuOne',
element: document.querySelector('.menu-one'),
}),
FloatingMenu.configure({
pluginKey: 'floatingMenuTwo',
element: document.querySelector('.menu-two'),
}),
],
})
```
Alternatively you can pass a ProseMirror `PluginKey`.
```js
import { Editor } from '@tiptap/core'
import FloatingMenu from '@tiptap/extension-floating-menu'
import { PluginKey } from '@tiptap/pm/state'
new Editor({
extensions: [
FloatingMenu.configure({
pluginKey: new PluginKey('floatingMenuOne'),
element: document.querySelector('.menu-one'),
}),
FloatingMenu.configure({
pluginKey: new PluginKey('floatingMenuOne'),
element: document.querySelector('.menu-two'),
}),
],
})
```

View File

@ -1,47 +0,0 @@
---
description: Keep track of where the cursor is, and let the user know you know it.
icon: focus-line
---
# Focus
[![Version](https://img.shields.io/npm/v/@tiptap/extension-focus.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-focus)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-focus.svg)](https://npmcharts.com/compare/@tiptap/extension-focus?minimal=true)
The Focus extension adds a CSS class to focused nodes. By default it adds `.has-focus`, but you can change that.
Note that its only a class, the styling is totally up to you. The usage example below has some CSS for that class.
## Installation
```bash
npm install @tiptap/extension-focus
```
## Settings
### className
The class that is applied to the focused element.
Default: `'has-focus'`
```js
Focus.configure({
className: 'focus',
})
```
### mode
Apply the class to `'all'`, the `'shallowest'` or the `'deepest'` node.
Default: `'all'`
```js
Focus.configure({
mode: 'deepest',
})
```
## Source code
[packages/extension-focus/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-focus/)
## Usage
https://embed.tiptap.dev/preview/Extensions/Focus

View File

@ -1,51 +0,0 @@
---
description: Doesnt have support for Comic Sans, but for all other fonts.
---
# FontFamily
[![Version](https://img.shields.io/npm/v/@tiptap/extension-font-family.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-font-family)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-font-family.svg)](https://npmcharts.com/compare/@tiptap/extension-font-family?minimal=true)
This extension enables you to set the font family in the editor. It uses the [`TextStyle`](/api/marks/text-style) mark, which renders a `<span>` tag. The font family is applied as inline style, for example `<span style="font-family: Arial">`.
## Installation
```bash
npm install @tiptap/extension-text-style @tiptap/extension-font-family
```
This extension requires the [`TextStyle`](/api/marks/text-style) mark.
## Settings
### types
A list of marks to which the font family attribute should be applied to.
Default: `['textStyle']`
```js
FontFamily.configure({
types: ['textStyle'],
})
```
## Commands
### setFontFamily()
Applies the given font family as inline style.
```js
editor.commands.setFontFamily('Inter')
```
### unsetFontFamily()
Removes any font family.
```js
editor.commands.unsetFontFamily()
```
## Source code
[packages/extension-font-family/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-font-family/)
## Usage
https://embed.tiptap.dev/preview/Extensions/FontFamily

View File

@ -1,27 +0,0 @@
---
description: The gapcursor makes sure the cursor doesnt get stuck … in a gap.
icon: space
---
# Gapcursor
[![Version](https://img.shields.io/npm/v/@tiptap/extension-gapcursor.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-gapcursor)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-gapcursor.svg)](https://npmcharts.com/compare/@tiptap/extension-gapcursor?minimal=true)
This extension loads the [ProseMirror Gapcursor plugin](https://github.com/ProseMirror/prosemirror-gapcursor) by Marijn Haverbeke, which adds a gap for the cursor in places that dont allow regular selection. For example, after a table at the end of a document.
Note that Tiptap is headless, but the gapcursor needs CSS for its appearance. The [default CSS](https://github.com/ueberdosis/tiptap/tree/main/packages/core/src/style.ts) is loaded through the Editor class.
## Installation
```bash
npm install @tiptap/extension-gapcursor
```
## Source code
[packages/extension-gapcursor/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-gapcursor/)
## Usage
https://embed.tiptap.dev/preview/Extensions/Gapcursor

View File

@ -1,76 +0,0 @@
---
description: If I could just go back and make everything undone … you can.
icon: history-line
---
# History
[![Version](https://img.shields.io/npm/v/@tiptap/extension-history.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-history)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-history.svg)](https://npmcharts.com/compare/@tiptap/extension-history?minimal=true)
This extension provides history support. All changes to the document will be tracked and can be removed with `undo`. Undone changes can be applied with `redo` again.
## Installation
```bash
npm install @tiptap/extension-history
```
## Settings
### depth
The amount of history events that are collected before the oldest events are discarded. Defaults to 100.
Default: `100`
```js
History.configure({
depth: 10,
})
```
### newGroupDelay
The delay between changes after which a new group should be started (in milliseconds). When changes arent adjacent, a new group is always started.
Default: `500`
```js
History.configure({
newGroupDelay: 1000,
})
```
## Commands
### undo()
Undo the last change.
```js
editor.commands.undo()
```
### redo()
Redo the last change.
```js
editor.commands.redo()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| undo() | `Control`&nbsp;`Z`<br>`Control`&nbsp;`я` | `Cmd`&nbsp;`Z`<br>`Cmd`&nbsp;`я` |
| redo() | `Shift`&nbsp;`Control`&nbsp;`Z`<br>`Control`&nbsp;`Y`<br>`Shift`&nbsp;`Control`&nbsp;`я` | `Shift`&nbsp;`Cmd`&nbsp;`Z`<br>`Cmd`&nbsp;`Y`<br>`Shift`&nbsp;`Cmd`&nbsp;`я` |
## Source code
[packages/extension-history/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-history/)
## Usage
https://embed.tiptap.dev/preview/Extensions/History

View File

@ -1,52 +0,0 @@
---
description: Add extra keymap handlers to change the default backspace and delete behavior for lists.
icon: asterisk
---
# ListKeymap
[![Version](https://img.shields.io/npm/v/@tiptap/extension-list-keymap.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-list-keymap)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-list-keymap.svg)](https://npmcharts.com/compare/@tiptap/extension-list-keymap?minimal=true)
This extensions adds extra keymap handlers to change the default backspace and delete behavior for lists. Those are not included in the core package, because they are not required for the most basic use cases.
## Installation
```bash
npm install @tiptap/extension-list-keymap
```
## Settings
### listTypes
A array of list items and their parent wrapper node types.
Default:
```js
[
{
itemName: 'listItem',
wrapperNames: ['bulletList', 'orderedList'],
},
{
itemName: 'taskItem',
wrapperNames: ['taskList'],
},
]
```
```js
ListKeymap.configure({
listTypes: [
{
itemName: 'taskItem',
wrapperNames: ['customTaskList'],
},
],
})
```
## Source code
[packages/extension-list-keymap/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-list-keymap/)
## Usage
https://embed.tiptap.dev/preview/Extensions/ListKeymap

View File

@ -1,140 +0,0 @@
---
description: Configure a helpful placeholder to fill the emptyness.
icon: ghost-line
---
# Placeholder
[![Version](https://img.shields.io/npm/v/@tiptap/extension-placeholder.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-placeholder)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-placeholder.svg)](https://npmcharts.com/compare/@tiptap/extension-placeholder?minimal=true)
This extension provides placeholder support. Give your users an idea what they should write with a tiny hint. There is a handful of things to customize, if you feel like it.
## Installation
```bash
npm install @tiptap/extension-placeholder
```
### Additional Setup
Placeholders are displayed with the help of CSS.
**Display a Placeholder only for the first line in an empty editor.**
```
.tiptap p.is-editor-empty:first-child::before {
color: #adb5bd;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
```
**Display Placeholders on every new line.**
```
.tiptap p.is-empty::before {
color: #adb5bd;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
```
## Settings
### emptyEditorClass
The added CSS class if the editor is empty.
Default: `'is-editor-empty'`
```js
Placeholder.configure({
emptyEditorClass: 'is-editor-empty',
})
```
### emptyNodeClass
The added CSS class if the node is empty.
Default: `'is-empty'`
```js
Placeholder.configure({
emptyNodeClass: 'my-custom-is-empty-class',
})
```
### placeholder
The placeholder text added as `data-placeholder` attribute.
Default: `'Write something …'`
```js
Placeholder.configure({
placeholder: 'My Custom Placeholder',
})
```
You can even use a function to add placeholder depending on the node:
```js
Placeholder.configure({
placeholder: ({ node }) => {
if (node.type.name === 'heading') {
return 'Whats the title?'
}
return 'Can you add some further context?'
},
})
```
### considerAnyAsEmpty
Consider any node that is not a leaf or atom as empty for the editor empty check.
Default: `false`
```js
Placeholder.configure({
considerAnyAsEmpty: true,
})
```
### showOnlyWhenEditable
Show decorations only when editor is editable.
Default: `true`
```js
Placeholder.configure({
showOnlyWhenEditable: false,
})
```
### showOnlyCurrent
Show decorations only in currently selected node.
Default: `true`
```js
Placeholder.configure({
showOnlyCurrent: false
})
```
### includeChildren
Show decorations also for nested nodes.
Default: `false`
```js
Placeholder.configure({
includeChildren: true
})
```
## Source code
[packages/extension-placeholder/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-placeholder/)
## Usage
https://embed.tiptap.dev/preview/Extensions/Placeholder

View File

@ -1,81 +0,0 @@
---
description: All the popular extensions in a single extension. Doesnt get much better than this.
icon: stack-line
---
# StarterKit
[![Version](https://img.shields.io/npm/v/@tiptap/starter-kit.svg?label=version)](https://www.npmjs.com/package/@tiptap/starter-kit)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/starter-kit.svg)](https://npmcharts.com/compare/@tiptap/starter-kit?minimal=true)
The `StarterKit` is a collection of the most popular Tiptap extensions. If youre just getting started, this extension is for you.
## Installation
```bash
npm install @tiptap/starter-kit
```
## Included extensions
### Nodes
* [`Blockquote`](/api/nodes/blockquote)
* [`BulletList`](/api/nodes/bullet-list)
* [`CodeBlock`](/api/nodes/code-block)
* [`Document`](/api/nodes/document)
* [`HardBreak`](/api/nodes/hard-break)
* [`Heading`](/api/nodes/heading)
* [`HorizontalRule`](/api/nodes/horizontal-rule)
* [`ListItem`](/api/nodes/list-item)
* [`OrderedList`](/api/nodes/ordered-list)
* [`Paragraph`](/api/nodes/paragraph)
* [`Text`](/api/nodes/text)
### Marks
* [`Bold`](/api/marks/bold)
* [`Code`](/api/marks/code)
* [`Italic`](/api/marks/italic)
* [`Strike`](/api/marks/strike)
### Extensions
* [`Dropcursor`](/api/extensions/dropcursor)
* [`Gapcursor`](/api/extensions/gapcursor)
* [`History`](/api/extensions/history)
## Source code
[packages/starter-kit/](https://github.com/ueberdosis/tiptap/blob/main/packages/starter-kit/)
## Usage
Pass `StarterKit` to the editor to load all included extension at once.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
const editor = new Editor({
content: '<p>Example Text</p>',
extensions: [
StarterKit,
],
})
```
You can configure the included extensions, or even disable a few of them, like shown below.
```js
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
const editor = new Editor({
content: '<p>Example Text</p>',
extensions: [
StarterKit.configure({
// Disable an included extension
history: false,
// Configure an included extension
heading: {
levels: [1, 2],
},
}),
],
})
```

View File

@ -1,85 +0,0 @@
---
description: Left, right, center, whatever! Align the text however you like.
icon: align-left
---
# TextAlign
[![Version](https://img.shields.io/npm/v/@tiptap/extension-text-align.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-text-align)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-text-align.svg)](https://npmcharts.com/compare/@tiptap/extension-text-align?minimal=true)
This extension adds a text align attribute to a specified list of nodes. The attribute is used to align the text.
:::warning Firefox bug
`text-align: justify` doesn't work together with `white-space: pre-wrap` in Firefox, [thats a known issue](https://bugzilla.mozilla.org/show_bug.cgi?id=1253840).
:::
## Installation
```bash
npm install @tiptap/extension-text-align
```
## Settings
### types
A list of nodes where the text align attribute should be applied to. Usually something like `['heading', 'paragraph']`.
Default: `[]`
```js
TextAlign.configure({
types: ['heading', 'paragraph'],
})
```
### alignments
A list of available options for the text align attribute.
Default: `['left', 'center', 'right', 'justify']`
```js
TextAlign.configure({
alignments: ['left', 'right'],
})
```
### defaultAlignment
The default text align.
Default: `'left'`
```js
TextAlign.configure({
defaultAlignment: 'right',
})
```
## Commands
### setTextAlign()
Set the text align to the specified value.
```js
editor.commands.setTextAlign('right')
```
### unsetTextAlign()
Remove the text align value.
```js
editor.commands.unsetTextAlign()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ----------------------- | ---------------------------- | --------------------------- |
| setTextAlign('left') | `Ctrl`&nbsp;`Shift`&nbsp;`L` | `Cmd`&nbsp;`Shift`&nbsp;`L` |
| setTextAlign('center') | `Ctrl`&nbsp;`Shift`&nbsp;`E` | `Cmd`&nbsp;`Shift`&nbsp;`E` |
| setTextAlign('right') | `Ctrl`&nbsp;`Shift`&nbsp;`R` | `Cmd`&nbsp;`Shift`&nbsp;`R` |
| setTextAlign('justify') | `Ctrl`&nbsp;`Shift`&nbsp;`J` | `Cmd`&nbsp;`Shift`&nbsp;`J` |
## Source code
[packages/extension-text-align/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-text-align/)
## Usage
https://embed.tiptap.dev/preview/Extensions/TextAlign

View File

@ -1,90 +0,0 @@
---
description: The typography smart ass for your editor, replaces everything thats wrong.
icon: quill-pen-line
---
# Typography
[![Version](https://img.shields.io/npm/v/@tiptap/extension-typography.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-typography)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-typography.svg)](https://npmcharts.com/compare/@tiptap/extension-typography?minimal=true)
This extension tries to help with common text patterns with the correct typographic character. Under the hood all rules are input rules.
## Installation
```bash
npm install @tiptap/extension-typography
```
## Rules
| Name | Description |
| ------------------- | --------------------------------------------------------------------------------------- |
| emDash | Converts double dashes `--` to an emdash `—`. |
| ellipsis | Converts three dots `...` to an ellipsis character `…` |
| openDoubleQuote | `“`Smart” opening double quotes. |
| closeDoubleQuote | “Smart`”` closing double quotes. |
| openSingleQuote | ``Smart opening single quotes. |
| closeSingleQuote | Smart`` closing single quotes. |
| leftArrow | Converts <code><&dash;</code> to an arrow `←` . |
| rightArrow | Converts <code>&dash;></code> to an arrow `→`. |
| copyright | Converts `(c)` to a copyright sign `©`. |
| registeredTrademark | Converts `(r)` to registered trademark sign `®`. |
| trademark | Converts `(tm)` to registered trademark sign `™`. |
| servicemark | Converts `(sm)` to registered trademark sign `℠`. |
| oneHalf | Converts `1/2` to one half `½`. |
| oneQuarter | Converts `1/4` to one quarter `¼`. |
| threeQuarters | Converts `3/4` to three quarters `¾`. |
| plusMinus | Converts `+/-` to plus/minus sign `±`. |
| notEqual | Converts <code style="font-variant-ligatures: none;">!=</code> to a not equal sign `≠`. |
| laquo | Converts `<<` to left-pointing double angle quotation mark `«`. |
| raquo | Converts `>>` to right-pointing double angle quotation mark `»`. |
| multiplication | Converts `2 * 3` or `2x3` to a multiplcation sign `2×3`. |
| superscriptTwo | Converts `^2` a superscript two `²`. |
| superscriptThree | Converts `^3` a superscript three `³`. |
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| --------------- | ------------- | ----------- |
| undoInputRule() | `Backspace` | `Backspace` |
## Source code
[packages/extension-typography/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-typography/)
## Usage
https://embed.tiptap.dev/preview/Extensions/Typography
### Disabling rules
You can configure the included rules, or even disable a few of them, like shown below.
```js
import { Editor } from '@tiptap/core'
import Typography from '@tiptap/extension-typography'
const editor = new Editor({
extensions: [
// Disable some included rules
Typography.configure({
oneHalf: false,
oneQuarter: false,
threeQuarters: false,
}),
],
})
```
### Overriding rules
You can override the output of a rule by passing a string to the option you want to override.
```js
import { Editor } from '@tiptap/core'
import Typography from '@tiptap/extension-typography'
const editor = new Editor({
extensions: [
// Disable some included rules
Typography.configure({
oneHalf: "1 / 2", // this will insert "1 / 2" instead of the default "½"
}),
],
})
```

View File

@ -1,27 +0,0 @@
# Introduction
Tiptap is a friendly wrapper around [ProseMirror](https://ProseMirror.net). Although Tiptap tries to hide most of the complexity of ProseMirror, its built on top of its APIs and we recommend you to read through the [ProseMirror Guide](https://ProseMirror.net/docs/guide/) for advanced usage.
### Structure
ProseMirror works with a strict [Schema](/api/schema), which defines the allowed structure of a document. A document is a tree of headings, paragraphs and others elements, so called nodes. Marks can be attached to a node, e. g. to emphasize part of it. [Commands](/api/commands) change that document programmatically.
### Content
The document is stored in a state. All changes are applied as transactions to the state. The state has details about the current content, cursor position and selection. You can hook into a few different [events](/api/events), for example to alter transactions before they get applied.
### Extensions
Extensions add [nodes](/api/nodes), [marks](/api/marks) and/or [functionalities](/api/extensions) to the editor. A lot of those extensions bound their commands to common [keyboard shortcuts](/api/keyboard-shortcuts).
## Vocabulary
ProseMirror has its own vocabulary and youll stumble upon all those words now and then. Here is a short overview of the most common words we use in the documentation.
| Word | Description |
| ----------- | ------------------------------------------------------------------------ |
| Schema | Configures the structure your content can have. |
| Document | The actual content in your editor. |
| State | Everything to describe the current content and selection of your editor. |
| Transaction | A change to the state (updated selection, content, …) |
| Extension | Registers new functionality. |
| Node | A type of content, for example a heading or a paragraph. |
| Mark | Can be applied to nodes, for example for inline formatting. |
| Command | Execute an action inside the editor, that somehow changes the state. |
| Decoration | Styling on top of the document, for example to highlight mistakes. |

View File

@ -1,101 +0,0 @@
---
tableOfContents: true
---
# Keyboard Shortcuts
## Introduction
Tiptap comes with sensible keyboard shortcut defaults. Depending on what you want to use it for, youll probably want to change those keyboard shortcuts to your liking. Lets have a look at what we defined for you, and show you how to change it then!
## Predefined keyboard shortcuts
Most of the core extensions register their own keyboard shortcuts. Depending on what set of extension you use, not all of the below listed keyboard shortcuts work for your editor.
### Essentials
| Command | Windows/Linux | macOS |
| ------------------------ | ------------------------------- | --------------------------- |
| Copy | `Control`&nbsp;`C` | `Cmd`&nbsp;`C` |
| Cut | `Control`&nbsp;`X` | `Cmd`&nbsp;`X` |
| Paste | `Control`&nbsp;`V` | `Cmd`&nbsp;`V` |
| Paste without formatting | `Control`&nbsp;`Shift`&nbsp;`V` | `Cmd`&nbsp;`Shift`&nbsp;`V` |
| Undo | `Control`&nbsp;`Z` | `Cmd`&nbsp;`Z` |
| Redo | `Control`&nbsp;`Shift`&nbsp;`Z` | `Cmd`&nbsp;`Shift`&nbsp;`Z` |
| Add a line break | `Shift`&nbsp;`Enter`<br>`Control`&nbsp;`Enter` | `Shift`&nbsp;`Enter`&nbsp;<br>`Cmd`&nbsp;`Enter` |
### Text Formatting
| Command | Windows/Linux | macOS |
| ------------- | ------------------------------- | --------------------------- |
| Bold | `Control`&nbsp;`B` | `Cmd`&nbsp;`B` |
| Italicize | `Control`&nbsp;`I` | `Cmd`&nbsp;`I` |
| Underline | `Control`&nbsp;`U` | `Cmd`&nbsp;`U` |
| Strikethrough | `Control`&nbsp;`Shift`&nbsp;`S` | `Cmd`&nbsp;`Shift`&nbsp;`S` |
| Highlight | `Control`&nbsp;`Shift`&nbsp;`H` | `Cmd`&nbsp;`Shift`&nbsp;`H` |
| Code | `Control`&nbsp;`E` | `Cmd`&nbsp;`E` |
### Paragraph Formatting
| Command | Windows/Linux | macOS |
| ----------------------- | ------------------------------- | --------------------------- |
| Apply normal text style | `Control`&nbsp;`Alt`&nbsp;`0` | `Cmd`&nbsp;`Alt`&nbsp;`0` |
| Apply heading style 1 | `Control`&nbsp;`Alt`&nbsp;`1` | `Cmd`&nbsp;`Alt`&nbsp;`1` |
| Apply heading style 2 | `Control`&nbsp;`Alt`&nbsp;`2` | `Cmd`&nbsp;`Alt`&nbsp;`2` |
| Apply heading style 3 | `Control`&nbsp;`Alt`&nbsp;`3` | `Cmd`&nbsp;`Alt`&nbsp;`3` |
| Apply heading style 4 | `Control`&nbsp;`Alt`&nbsp;`4` | `Cmd`&nbsp;`Alt`&nbsp;`4` |
| Apply heading style 5 | `Control`&nbsp;`Alt`&nbsp;`5` | `Cmd`&nbsp;`Alt`&nbsp;`5` |
| Apply heading style 6 | `Control`&nbsp;`Alt`&nbsp;`6` | `Cmd`&nbsp;`Alt`&nbsp;`6` |
| Ordered list | `Control`&nbsp;`Shift`&nbsp;`7` | `Cmd`&nbsp;`Shift`&nbsp;`7` |
| Bullet list | `Control`&nbsp;`Shift`&nbsp;`8` | `Cmd`&nbsp;`Shift`&nbsp;`8` |
| Task list | `Control`&nbsp;`Shift`&nbsp;`9` | `Cmd`&nbsp;`Shift`&nbsp;`9` |
| Blockquote | `Control`&nbsp;`Shift`&nbsp;`B` | `Cmd`&nbsp;`Shift`&nbsp;`B` |
| Left align | `Control`&nbsp;`Shift`&nbsp;`L` | `Cmd`&nbsp;`Shift`&nbsp;`L` |
| Center align | `Control`&nbsp;`Shift`&nbsp;`E` | `Cmd`&nbsp;`Shift`&nbsp;`E` |
| Right align | `Control`&nbsp;`Shift`&nbsp;`R` | `Cmd`&nbsp;`Shift`&nbsp;`R` |
| Justify | `Control`&nbsp;`Shift`&nbsp;`J` | `Cmd`&nbsp;`Shift`&nbsp;`J` |
| Code block | `Control`&nbsp;`Alt`&nbsp;`C` | `Cmd`&nbsp;`Alt`&nbsp;`C` |
| Subscript | `Control`&nbsp;`,` | `Cmd`&nbsp;`,` |
| Superscript | `Control`&nbsp;`.` | `Cmd`&nbsp;`.` |
<!--| Toggle task| `Control`&nbsp;`Enter` | `Cmd`&nbsp;`Enter` | -->
### Text Selection
| Command | Windows/Linux | macOS |
| ------------------------------------------------- | ------------------------------- | --------------------------- |
| Select all | `Control`&nbsp;`A` | `Cmd`&nbsp;`A` |
| Extend selection one character to left | `Shift`&nbsp;`←` | `Shift`&nbsp;`←` |
| Extend selection one character to right | `Shift`&nbsp;`→` | `Shift`&nbsp;`→` |
| Extend selection one line up | `Shift`&nbsp;`↑` | `Shift`&nbsp;`↑` |
| Extend selection one line down | `Shift`&nbsp;`↓` | `Shift`&nbsp;`↓` |
| Extend selection to the beginning of the document | `Control`&nbsp;`Shift`&nbsp;`↑` | `Cmd`&nbsp;`Shift`&nbsp;`↑` |
| Extend selection to the end of the document | `Control`&nbsp;`Shift`&nbsp;`↓` | `Cmd`&nbsp;`Shift`&nbsp;`↓` |
## Overwrite keyboard shortcuts
Keyboard shortcuts may be strings like `'Shift-Control-Enter'`. Keys are based on the strings that can appear in `event.key`, concatenated with a `-`. There is a little tool called [keycode.info](https://keycode.info/), which shows the `event.key` interactively.
Use lowercase letters to refer to letter keys (or uppercase letters if you want shift to be held). You may use `Space` as an alias for the <code>&nbsp;</code>.
Modifiers can be given in any order. `Shift`, `Alt`, `Control` and `Cmd` are recognized. For characters that are created by holding shift, the `Shift` prefix is implied, and should not be added explicitly.
You can use `Mod` as a shorthand for `Cmd` on Mac and `Control` on other platforms.
Here is an example how you can overwrite the keyboard shortcuts for an existing extension:
```js
// 1. Import the extension
import BulletList from '@tiptap/extension-bullet-list'
// 2. Overwrite the keyboard shortcuts
const CustomBulletList = BulletList.extend({
addKeyboardShortcuts() {
return {
// ↓ your new keyboard shortcut
'Mod-l': () => this.editor.commands.toggleBulletList(),
}
},
})
// 3. Add the custom extension to your editor
new Editor({
extensions: [
CustomBulletList(),
// …
],
})
```

View File

@ -1,22 +0,0 @@
---
tableOfContents: true
---
# Marks
## Introduction
One or multiple marks can be applied to [nodes](/api/nodes), for example to add inline formatting like bold and italic, or other additional information.
## List of supported marks
| Title | StarterKit ([view](/api/extensions/starter-kit)) | Source Code |
| ------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| [Bold](/api/marks/bold) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-bold/) |
| [Code](/api/marks/code) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-code/) |
| [Highlight](/api/marks/highlight) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-highlight/) |
| [Italic](/api/marks/italic) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-italic/) |
| [Link](/api/marks/link) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-link/) |
| [Strike](/api/marks/strike) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-strike/) |
| [Subscript](/api/marks/subscript) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-subscript/) |
| [Superscript](/api/marks/superscript) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-superscript/) |
| [TextStyle](/api/marks/text-style) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-text-style/) |
| [Underline](/api/marks/underline) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-underline/) |

View File

@ -1,68 +0,0 @@
---
description: Make your text bold and let it stand out.
icon: bold
---
# Bold
[![Version](https://img.shields.io/npm/v/@tiptap/extension-bold.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-bold)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-bold.svg)](https://npmcharts.com/compare/@tiptap/extension-bold?minimal=true)
Use this extension to render text in **bold**. If you pass `<strong>`, `<b>` tags, or text with inline `style` attributes setting the `font-weight` CSS rule in the editors initial content, they all will be rendered accordingly.
Type `**two asterisks**` or `__two underlines__` and it will magically transform to **bold** text while you type.
::: warning Restrictions
The extension will generate the corresponding `<strong>` HTML tags when reading contents of the `Editor` instance. All text marked bold, regardless of the method will be normalized to `<strong>` HTML tags.
:::
## Installation
```bash
npm install @tiptap/extension-bold
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Bold.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setBold()
Mark text as bold.
```js
editor.commands.setBold()
```
### toggleBold()
Toggle the bold mark.
```js
editor.commands.toggleBold()
```
### unsetBold()
Remove the bold mark.
```js
editor.commands.unsetBold()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ------------ | ------------------ | -------------- |
| toggleBold() | `Control`&nbsp;`B` | `Cmd`&nbsp;`B` |
## Source code
[packages/extension-bold/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-bold/)
## Usage
https://embed.tiptap.dev/preview/Marks/Bold

View File

@ -1,64 +0,0 @@
---
description: Developers love to add some inline code to their texts.
icon: code-view
---
# Code
[![Version](https://img.shields.io/npm/v/@tiptap/extension-code.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-code)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-code.svg)](https://npmcharts.com/compare/@tiptap/extension-code?minimal=true)
The Code extensions enables you to use the `<code>` HTML tag in the editor. If you paste in text with `<code>` tags it will rendered accordingly.
Type something with <code>\`back-ticks around\`</code> and it will magically transform to `inline code` while you type.
## Installation
```bash
npm install @tiptap/extension-code
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Code.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setCode()
Mark text as inline code.
```js
editor.commands.setCode()
```
### toggleCode()
Toggle inline code mark.
```js
editor.commands.toggleCode()
```
### unsetCode()
Remove inline code mark.
```js
editor.commands.unsetCode()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ------------ | ------------------ | -------------- |
| toggleCode() | `Control`&nbsp;`E` | `Cmd`&nbsp;`E` |
## Source code
[packages/extension-code/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-code/)
## Usage
https://embed.tiptap.dev/preview/Marks/Code

View File

@ -1,78 +0,0 @@
---
description: Make it look nerdier with some colorful text highlights.
icon: mark-pen-line
---
# Highlight
[![Version](https://img.shields.io/npm/v/@tiptap/extension-highlight.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-highlight)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-highlight.svg)](https://npmcharts.com/compare/@tiptap/extension-highlight?minimal=true)
Use this extension to render highlighted text with `<mark>`. You can use only default `<mark>` HTML tag, which has a yellow background color by default, or apply different colors.
Type `==two equal signs==` and it will magically transform to <mark>highlighted</mark> text while you type.
## Installation
```bash
npm install @tiptap/extension-highlight
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Highlight.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
### multicolor
Add support for multiple colors.
Default: `false`
```js
Highlight.configure({
multicolor: true,
})
```
## Commands
### setHighlight()
Mark text as highlighted.
```js
editor.commands.setHighlight()
editor.commands.setHighlight({ color: '#ffcc00' })
```
### toggleHighlight()
Toggle a text highlight.
```js
editor.commands.toggleHighlight()
editor.commands.toggleHighlight({ color: '#ffcc00' })
```
### unsetHighlight()
Removes the highlight.
```js
editor.commands.unsetHighlight()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ----------------- | ------------------------------- | --------------------------- |
| toggleHighlight() | `Control`&nbsp;`Shift`&nbsp;`H` | `Cmd`&nbsp;`Shift`&nbsp;`H` |
## Source code
[packages/extension-highlight/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-highlight/)
## Usage
https://embed.tiptap.dev/preview/Marks/Highlight

View File

@ -1,68 +0,0 @@
---
description: Helps to emphasize your text, doesnt bring you closer to Italy though.
icon: italic
---
# Italic
[![Version](https://img.shields.io/npm/v/@tiptap/extension-italic.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-italic)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-italic.svg)](https://npmcharts.com/compare/@tiptap/extension-italic?minimal=true)
Use this extension to render text in *italic*. If you pass `<em>`, `<i>` tags, or text with inline `style` attributes setting `font-style: italic` in the editors initial content, they all will be rendered accordingly.
Type `*one asterisk*` or `_one underline_` and it will magically transform to *italic* text while you type.
::: warning Restrictions
The extension will generate the corresponding `<em>` HTML tags when reading contents of the `Editor` instance. All text marked italic, regardless of the method will be normalized to `<em>` HTML tags.
:::
## Installation
```bash
npm install @tiptap/extension-italic
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Italic.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setItalic()
Mark the text italic.
```js
editor.commands.setItalic()
```
### toggleItalic()
Toggle the italic mark.
```js
editor.commands.toggleItalic()
```
### unsetItalic()
Remove the italic mark.
```js
editor.commands.unsetItalic()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| -------------- | ------------------ | -------------- |
| toggleItalic() | `Control`&nbsp;`I` | `Cmd`&nbsp;`I` |
## Source code
[packages/extension-italic/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-italic/)
## Usage
https://embed.tiptap.dev/preview/Marks/Italic

View File

@ -1,175 +0,0 @@
---
description: Link it, link it good, link it real good (and dont forget the href).
icon: link
---
# Link
[![Version](https://img.shields.io/npm/v/@tiptap/extension-link.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-link)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-link.svg)](https://npmcharts.com/compare/@tiptap/extension-link?minimal=true)
The Link extension adds support for `<a>` tags to the editor. The extension is headless too, there is no actual UI to add, modify or delete links. The usage example below uses the native JavaScript prompt to show you how that could work.
In a real world application, you would probably add a more sophisticated user interface.
Pasted URLs will be transformed to links automatically.
## Installation
```bash
npm install @tiptap/extension-link
```
## Settings
### protocols
Additional custom protocols you would like to be recognized as links.
Default: `[]`
```js
Link.configure({
protocols: ['ftp', 'mailto'],
})
```
By default, [linkify](https://linkify.js.org/docs/) adds `//` to the end of a protocol however this behavior can be changed by passing `optionalSlashes` option
```js
Link.configure({
protocols: [
{
scheme: 'tel',
optionalSlashes: true
}
]
})
```
### autolink
If enabled, it adds links as you type.
Default: `true`
```js
Link.configure({
autolink: false,
})
```
### openOnClick
If enabled, links will be opened on click.
Default: `true`
```js
Link.configure({
openOnClick: false,
})
```
### linkOnPaste
Adds a link to the current selection if the pasted content only contains an url.
Default: `true`
```js
Link.configure({
linkOnPaste: false,
})
```
### default protocol
The default protocol used by `linkOnPaste` and `autolink` when no protocol is defined.
By default, the href generated for example.com is http://example.com and this option allows that protocol to be customized.
Default: `http`
```js
Link.configure({
defaultProtocol: 'https',
})
```
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Link.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
#### Removing and overriding existing html attributes
You can add `rel: null` to HTMLAttributes to remove the default `rel="noopener noreferrer nofollow"`. You can also override the default by using `rel: "your-value"`.
This can also be used to change the `target` from the default value of `_blank`.
```js
Link.configure({
HTMLAttributes: {
// Change rel to different value
// Allow search engines to follow links(remove nofollow)
rel: 'noopener noreferrer',
// Remove target entirely so links open in current tab
target: null,
},
})
```
### validate
A function that validates every autolinked link. If it exists, it will be called with the link href as argument. If it returns `false`, the link will be removed.
Can be used to set rules for example excluding or including certain domains, tlds, etc.
```js
// only autolink urls with a protocol
Link.configure({
validate: href => /^https?:\/\//.test(href),
})
```
## Commands
### setLink()
Links the selected text.
```js
editor.commands.setLink({ href: 'https://example.com' })
editor.commands.setLink({ href: 'https://example.com', target: '_blank' })
```
### toggleLink()
Adds or removes a link from the selected text.
```js
editor.commands.toggleLink({ href: 'https://example.com' })
editor.commands.toggleLink({ href: 'https://example.com', target: '_blank' })
```
### unsetLink()
Removes a link.
```js
editor.commands.unsetLink()
```
## Keyboard shortcuts
:::warning Doesnt have a keyboard shortcut
This extension doesnt bind a specific keyboard shortcut. You would probably open your custom UI on `Mod-k` though.
:::
## Get the current value
Did you know that you can use [`getAttributes`](/api/editor#get-attributes) to find out which attributes, for example which href, is currently set? Dont confuse it with a [command](/api/commands) (which changes the state), its just a method. Here is how that could look like:
```js
this.editor.getAttributes('link').href
```
## Source code
[packages/extension-link/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-link/)
## Usage
https://embed.tiptap.dev/preview/Marks/Link

View File

@ -1,68 +0,0 @@
---
description: Cut through the words you wrote if youre too afraid to delete it.
icon: strikethrough
---
# Strike
[![Version](https://img.shields.io/npm/v/@tiptap/extension-strike.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-strike)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-strike.svg)](https://npmcharts.com/compare/@tiptap/extension-strike?minimal=true)
Use this extension to render ~~striked text~~. If you pass `<s>`, `<del>`, `<strike>` tags, or text with inline `style` attributes setting `text-decoration: line-through` in the editors initial content, they all will be rendered accordingly.
Type <code>&Tilde;&Tilde;text between tildes&Tilde;&Tilde;</code> and it will be magically ~~striked through~~ while you type.
::: warning Restrictions
The extension will generate the corresponding `<s>` HTML tags when reading contents of the `Editor` instance. All text striked through, regardless of the method will be normalized to `<s>` HTML tags.
:::
## Installation
```bash
npm install @tiptap/extension-strike
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Strike.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setStrike()
Mark text as striked.
```js
editor.commands.setStrike()
```
### toggleStrike()
Toggle strike mark.
```js
editor.commands.toggleStrike()
```
### unsetStrike()
Remove strike mark.
```js
editor.commands.unsetStrike()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| -------------- | ------------------------------- | --------------------------- |
| toggleStrike() | `Control`&nbsp;`Shift`&nbsp;`S` | `Cmd`&nbsp;`Shift`&nbsp;`S` |
## Source code
[packages/extension-strike/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-strike/)
## Usage
https://embed.tiptap.dev/preview/Marks/Strike

View File

@ -1,66 +0,0 @@
---
description: Write slightly below the normal line to show youre unique.
icon: subscript
---
# Subscript
[![Version](https://img.shields.io/npm/v/@tiptap/extension-subscript.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-subscript)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-subscript.svg)](https://npmcharts.com/compare/@tiptap/extension-subscript?minimal=true)
Use this extension to render text in <sub>subscript</sub>. If you pass `<sub>` or text with `vertical-align: sub` as inline style in the editors initial content, both will be rendered accordingly.
::: warning Restrictions
The extension will generate the corresponding `<sub>` HTML tags when reading contents of the `Editor` instance. All text in subscript, regardless of the method will be normalized to `<sub>` HTML tags.
:::
## Installation
```bash
npm install @tiptap/extension-subscript
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Subscript.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setSubscript()
Mark text as subscript.
```js
editor.commands.setSubscript()
```
### toggleSubscript()
Toggle subscript mark.
```js
editor.commands.toggleSubscript()
```
### unsetSubscript()
Remove subscript mark.
```js
editor.commands.unsetSubscript()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ----------------- | ------------------ | -------------- |
| toggleSubscript() | `Control`&nbsp;`,` | `Cmd`&nbsp;`,` |
## Source code
[packages/extension-subscript/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-subscript/)
## Usage
https://embed.tiptap.dev/preview/Marks/Subscript

View File

@ -1,66 +0,0 @@
---
description: Write slightly above the normal line to show youre just next level.
icon: superscript
---
# Superscript
[![Version](https://img.shields.io/npm/v/@tiptap/extension-superscript.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-superscript)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-superscript.svg)](https://npmcharts.com/compare/@tiptap/extension-superscript?minimal=true)
Use this extension to render text in <sup>superscript</sup>. If you pass `<sup>` or text with `vertical-align: super` as inline style in the editors initial content, both will be rendered accordingly.
::: warning Restrictions
The extension will generate the corresponding `<sup>` HTML tags when reading contents of the `Editor` instance. All text in superscript, regardless of the method will be normalized to `<sup>` HTML tags.
:::
## Installation
```bash
npm install @tiptap/extension-superscript
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Superscript.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setSuperscript()
Mark text as superscript.
```js
editor.commands.setSuperscript()
```
### toggleSuperscript()
Toggle superscript mark.
```js
editor.commands.toggleSuperscript()
```
### unsetSuperscript()
Remove superscript mark.
```js
editor.commands.unsetSuperscript()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ------------------- | ------------------ | -------------- |
| toggleSuperscript() | `Control`&nbsp;`.` | `Cmd`&nbsp;`.` |
## Source code
[packages/extension-superscript/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-superscript/)
## Usage
https://embed.tiptap.dev/preview/Marks/Superscript

View File

@ -1,30 +0,0 @@
---
description: Useless extension, just adds <span> tags (required by other extensions though).
icon: palette-line
---
# TextStyle
[![Version](https://img.shields.io/npm/v/@tiptap/extension-text-style.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-text-style)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-text-style.svg)](https://npmcharts.com/compare/@tiptap/extension-text-style?minimal=true)
This mark renders a `<span>` HTML tag and enables you to add a list of styling related attributes, for example font-family, font-size, or color. The extension doesnt add any styling attribute by default, but other extensions use it as the foundation, for example [`FontFamily`](/api/extensions/font-family) or [`Color`](/api/extensions/color).
## Installation
```bash
npm install @tiptap/extension-text-style
```
## Commands
### removeEmptyTextStyle()
Remove `<span>` tags without an inline style.
```js
editor.command.removeEmptyTextStyle()
```
## Source code
[packages/extension-text-style/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-text-style/)
## Usage
https://embed.tiptap.dev/preview/Marks/TextStyle

View File

@ -1,68 +0,0 @@
---
description: Add a line below your text to make it look more … underlined.
icon: underline
---
# Underline
[![Version](https://img.shields.io/npm/v/@tiptap/extension-underline.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-underline)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-underline.svg)](https://npmcharts.com/compare/@tiptap/extension-underline?minimal=true)
Use this extension to render text <u>underlined</u>. If you pass `<u>` tags, or text with inline `style` attributes setting `text-decoration: underline` in the editors initial content, they all will be rendered accordingly.
Be aware that underlined text in the internet usually indicates that its a clickable link. Dont confuse your users with underlined text.
::: warning Restrictions
The extension will generate the corresponding `<u>` HTML tags when reading contents of the `Editor` instance. All text marked underlined, regardless of the method will be normalized to `<u>` HTML tags.
:::
## Installation
```bash
npm install @tiptap/extension-underline
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Underline.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setUnderline()
Marks a text as underlined.
```js
editor.commands.setUnderline()
```
### toggleUnderline()
Toggles an underline mark.
```js
editor.commands.toggleUnderline()
```
### unsetUnderline()
Removes an underline mark.
```js
editor.commands.unsetUnderline()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ----------------- | ------------------ | -------------- |
| toggleUnderline() | `Control`&nbsp;`U` | `Cmd`&nbsp;`U` |
## Source code
[packages/extension-underline/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-underline/)
## Usage
https://embed.tiptap.dev/preview/Marks/Underline

View File

@ -1,313 +0,0 @@
---
tableOfContents: true
---
# Node Positions
## Introduction
Node Positions (short `NodePos`) are a new concept introduced with Tiptap 2.2.0. They are used to describe a specific position of a node, it's children, it's parent and easy ways to navigate between them. They are heavily inspired by the DOM and are based on Prosemirror's [ResolvedPos](https://prosemirror.net/docs/ref/#model.ResolvedPos) implementation.
## Usage
The easiest way to create a new **Node Position** is to use the helper functions added to the Editor instance. This way you always use the correct editor instance and have direct access to the API.
```js
// set up your editor somewhere up here
// The NodePosition for the outermost document node
const $doc = editor.$doc
// This will get all nodes with the type 'heading' currently found in the document
const $headings = editor.$nodes('heading')
// You can also combine this to filter by attributes
const $h1 = editor.$nodes('heading', { level: 1 })
// You can also pick nodes directly:
const $firstHeading = editor.$node('heading', { level: 1 })
// If you don't know the type but the position you want to work with, you can create a new NodePos via the $pos method
const $myCustomPos = editor.$pos(30)
```
You can also create your own NodePos instances:
```js
// You need to have an editor instance
// and a position you want to map to
const myNodePos = new NodePos(100, editor)
```
## What can I do with a NodePos?
NodePos can be used to traverse the document similar to the document DOM of your browser. You can access the parent node, child nodes and the sibling nodes. Here are an example of what you can do with a `codeBlock` node:
```js
// get the first codeBlock from your document
const $codeBlock = editor.$node('codeBlock')
// get the previous NodePos of your codeBlock node
const $previousItem = $codeBlock.before
// easily update the content
$previousItem.content = '<p>Updated content</p>'
```
If you are familiar with the DOM the following example should look familiar to you:
```js
// get a bullet list from your doc
const $bulletList = editor.$node('bulletList')
// get all listItems from your bulletList
const $listItems = $bulletList.querySelectorAll('listItem')
// get the last listItem
const $lastListItem = $listItems[0]
// insert a new listItem after the last one
editor.commands.insertContentAt($lastListItem.after, '<li>New item</li>')
```
## API
### NodePos
The NodePos class is the main class you will work with. It is used to describe a specific position of a node, it's children, it's parent and easy ways to navigate between them. They are heavily inspired by the DOM and are based on Prosemirror's [ResolvedPos](https://prosemirror.net/docs/ref/#model.ResolvedPos) implementation.
#### Methods
##### constructor
**Arguments**
- `pos` The position you want to map to
- `editor` The editor instance you want to use
**Returns** `NodePos`
```js
const myNodePos = new NodePos(100, editor)
```
##### closest
The closest NodePos instance of your NodePosition going up the depth. If there is no matching NodePos, it will return `null`.
**Returns** `NodePos | null`
```js
const closest = myNodePos.closest('bulletList')
```
##### querySelector
The first matching NodePos instance of your NodePosition going down the depth. If there is no matching NodePos, it will return `null`.
You can also filter by attributes via the second attribute.
**Returns** `NodePos | null`
```js
const firstHeading = myNodePos.querySelector('heading')
const firstH1 = myNodePos.querySelector('heading', { level: 1 })
```
##### querySelectorAll
All matching NodePos instances of your NodePosition going down the depth. If there is no matching NodePos, it will return an empty array.
You can also filter by attributes via the second attribute.
**Returns** `Array<NodePos>`
```js
const headings = myNodePos.querySelectorAll('heading')
const h1s = myNodePos.querySelectorAll('heading', { level: 1 })
```
##### setAttributes
Set attributes on the current NodePos.
**Returns** `NodePos`
```js
myNodePos.setAttributes({ level: 1 })
```
#### Properties
##### node
The Prosemirror Node at the current Node Position.
**Returns** `Node`
```js
const node = myNodePos.node
node.type.name // 'paragraph'
```
##### element
The DOM element at the current Node Position.
**Returns** `Element`
```js
const element = myNodePos.element
element.tagName // 'P'
```
##### content
The content of your NodePosition. This can be set to a new value to update the content of the node.
**Returns** `string`
```js
const content = myNodePos.content
myNodePos.content = '<p>Updated content</p>'
```
##### attributes
The attributes of your NodePosition.
**Returns** `Object`
```js
const attributes = myNodePos.attributes
attributes.level // 1
```
##### textContent
The text content of your NodePosition.
**Returns** `string`
```js
const textContent = myNodePos.textContent
```
##### depth
The depth of your NodePosition.
**Returns** `number`
```js
const depth = myNodePos.depth
```
##### pos
The position of your NodePosition.
**Returns** `number`
```js
const pos = myNodePos.pos
```
##### size
The size of your NodePosition.
**Returns** `number`
```js
const size = myNodePos.size
```
##### from
The from position of your NodePosition.
**Returns** `number`
```js
const from = myNodePos.from
```
##### to
The to position of your NodePosition.
**Returns** `number`
```js
const to = myNodePos.to
```
##### range
The range of your NodePosition.
**Returns** `number`
```js
const range = myNodePos.range
```
##### parent
The parent NodePos of your NodePosition.
**Returns** `NodePos`
```js
const parent = myNodePos.parent
```
##### before
The NodePos before your NodePosition. If there is no NodePos before, it will return `null`.
**Returns** `NodePos | null`
```js
const before = myNodePos.before
```
##### after
The NodePos after your NodePosition. If there is no NodePos after, it will return `null`.
**Returns** `NodePos | null`
```js
const after = myNodePos.after
```
##### children
The child NodePos instances of your NodePosition.
**Returns** `Array<NodePos>`
```js
const children = myNodePos.children
```
##### firstChild
The first child NodePos instance of your NodePosition. If there is no child, it will return `null`.
**Returns** `NodePos | null`
```js
const firstChild = myNodePos.firstChild
```
##### lastChild
The last child NodePos instance of your NodePosition. If there is no child, it will return `null`.
**Returns** `NodePos | null`
```js
const lastChild = myNodePos.lastChild
```

View File

@ -1,60 +0,0 @@
---
tableOfContents: true
---
# Nodes
## Introduction
If you think of the document as a tree, then nodes are just a type of content in that tree. Examples of nodes are paragraphs, headings, or code blocks. But nodes dont have to be blocks. They can also be rendered inline with the text, for example for **@mentions**.
## List of supported nodes
| Title | StarterKit ([view](/api/extensions/starter-kit)) | Source Code |
| -------------------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| [Blockquote](/api/nodes/blockquote) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-blockquote/) |
| [BulletList](/api/nodes/bullet-list) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-bullet-list/) |
| [CodeBlock](/api/nodes/code-block) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-code-block/) |
| [Details](/api/nodes/details) | | Requires a Tiptap Pro subscription |
| [DetailsSummary](/api/nodes/details-summary) | | Requires a Tiptap Pro subscription |
| [DetailsContent](/api/nodes/details-content) | | Requires a Tiptap Pro subscription |
| [Document](/api/nodes/document) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-document/) |
| [Emoji](/api/nodes/emoji) | | Requires a Tiptap Pro subscription |
| [HardBreak](/api/nodes/hard-break) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-hard-break/) |
| [Heading](/api/nodes/heading) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-heading/) |
| [HorizontalRule](/api/nodes/horizontal-rule) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-horizontal-rule/) |
| [Image](/api/nodes/image) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-image/) |
| [ListItem](/api/nodes/list-item) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-list-item/) |
| [Mention](/api/nodes/mention) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-mention/) |
| [OrderedList](/api/nodes/ordered-list) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-ordered-list/) |
| [Paragraph](/api/nodes/paragraph) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-paragraph/) |
| [Table](/api/nodes/table) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-table/) |
| [TableRow](/api/nodes/table-row) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-table-row/) |
| [TableCell](/api/nodes/table-cell) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-table-cell/) |
| [TaskList](/api/nodes/task-list) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-task-list/) |
| [TaskItem](/api/nodes/task-item) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-task-item/) |
| [Text](/api/nodes/text) | Included | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-text/) |
| [YouTube](/api/nodes/youtube) | | [GitHub](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-youtube/) |
## Create a new node
Youre free to create your own nodes for Tiptap. Here is the boilerplate code thats need to create and register your own node:
```js
import { Node } from '@tiptap/core'
const CustomNode = Node.create({
// Your code here
})
const editor = new Editor({
extensions: [
// Register your custom node with the editor.
CustomNode,
// … and dont forget all other extensions.
Document,
Paragraph,
Text,
// …
],
})
```
Learn [more about custom extensions in our guide](/guide/custom-extensions).

View File

@ -1,63 +0,0 @@
---
description: Quoting other people will make you look clever.
icon: double-quotes-l
---
# Blockquote
[![Version](https://img.shields.io/npm/v/@tiptap/extension-blockquote.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-blockquote)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-blockquote.svg)](https://npmcharts.com/compare/@tiptap/extension-blockquote?minimal=true)
The Blockquote extension enables you to use the `<blockquote>` HTML tag in the editor. This is great to … show quotes in the editor, you know?
Type <code>>&nbsp;</code> at the beginning of a new line and it will magically transform to a blockquote.
## Installation
```bash
npm install @tiptap/extension-blockquote
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Blockquote.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setBlockquote()
Wrap content in a blockquote.
```js
editor.commands.setBlockquote()
```
### toggleBlockquote()
Wrap or unwrap a blockquote.
```js
editor.commands.toggleBlockquote()
```
### unsetBlockquote()
Unwrap a blockquote.
```js
editor.commands.unsetBlockquote()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ----------------- | ------------------------------- | --------------------------- |
| Toggle Blockquote | `Control`&nbsp;`Shift`&nbsp;`B` | `Cmd`&nbsp;`Shift`&nbsp;`B` |
## Source code
[packages/extension-blockquote/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-blockquote/)
## Usage
https://embed.tiptap.dev/preview/Nodes/Blockquote

View File

@ -1,84 +0,0 @@
---
description: Everything looks more serious with a few bullet points.
icon: list-unordered
---
# BulletList
[![Version](https://img.shields.io/npm/v/@tiptap/extension-bullet-list.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-bullet-list)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-bullet-list.svg)](https://npmcharts.com/compare/@tiptap/extension-bullet-list?minimal=true)
This extension enables you to use bullet lists in the editor. They are rendered as `<ul>` HTML tags.
Type <code>*&nbsp;</code>, <code>-&nbsp;</code> or <code>+&nbsp;</code> at the beginning of a new line and it will magically transform to a bullet list.
## Installation
```bash
npm install @tiptap/extension-bullet-list @tiptap/extension-list-item
```
This extension requires the [`ListItem`](/api/nodes/list-item) node.
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
BulletList.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
### itemTypeName
Specify the list item name.
Default: `'listItem'`
```js
BulletList.configure({
itemTypeName: 'listItem',
})
```
### keepMarks
Decides whether to keep the marks from a previous line after toggling the list either using `inputRule` or using the button
Default: `false`
```js
BulletList.configure({
keepMarks: true,
})
```
### keepAttributes
Decides whether to keep the attributes from a previous line after toggling the list either using `inputRule` or using the button
Default: `false`
```js
BulletList.configure({
keepAttributes: true,
})
```
## Commands
### toggleBulletList()
Toggles a bullet list.
```js
editor.commands.toggleBulletList()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ---------------- | ------------------------------- | --------------------------- |
| toggleBulletList | `Control`&nbsp;`Shift`&nbsp;`8` | `Cmd`&nbsp;`Shift`&nbsp;`8` |
## Source code
[packages/extension-bullet-list/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-bullet-list/)
## Usage
https://embed.tiptap.dev/preview/Nodes/BulletList

View File

@ -1,97 +0,0 @@
---
description: Add some colorful syntax highlighting to your code blocks.
icon: terminal-box-fill
---
# CodeBlockLowlight
[![Version](https://img.shields.io/npm/v/@tiptap/extension-code-block-lowlight.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-code-block-lowlight)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-code-block-lowlight.svg)](https://npmcharts.com/compare/@tiptap/extension-code-block-lowlight?minimal=true)
With the CodeBlockLowlight extension you can add fenced code blocks to your documents. Itll wrap the code in `<pre>` and `<code>` HTML tags.
::: warning Syntax highlight dependency
This extension relies on the [lowlight](https://github.com/wooorm/lowlight) library to apply syntax highlight to the code blocks content.
:::
Type <code>&grave;&grave;&grave;&nbsp;</code> (three backticks and a space) or <code>&Tilde;&Tilde;&Tilde;&nbsp;</code> (three tildes and a space) and a code block is instantly added for you. You can even specify the language, try writing <code>&grave;&grave;&grave;css&nbsp;</code>. That should add a `language-css` class to the `<code>`-tag.
## Installation
```bash
npm install lowlight @tiptap/extension-code-block-lowlight
```
## Settings
### lowlight
You should provide the `lowlight` module to this extension. Decoupling the `lowlight`
package from the extension allows the client application to control which
version of lowlight it uses and which programming language packages it needs to load.
```js
import { lowlight } from 'lowlight/lib/core'
CodeBlockLowlight.configure({
lowlight,
})
```
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
CodeBlockLowlight.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
### languageClassPrefix
Adds a prefix to language classes that are applied to code tags.
Default: `'language-'`
```js
CodeBlockLowlight.configure({
languageClassPrefix: 'language-',
})
```
### defaultLanguage
Define a default language instead of the automatic detection of lowlight.
Default: `null`
```js
CodeBlockLowlight.configure({
defaultLanguage: 'plaintext',
})
```
## Commands
### setCodeBlock()
Wrap content in a code block.
```js
editor.commands.setCodeBlock()
```
### toggleCodeBlock()
Toggle the code block.
```js
editor.commands.toggleCodeBlock()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| --------------- | ----------------------------- | ------------------------- |
| toggleCodeBlock | `Control`&nbsp;`Alt`&nbsp;`C` | `Cmd`&nbsp;`Alt`&nbsp;`C` |
## Source code
[packages/extension-code-block-lowlight/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-code-block-lowlight/)
## Usage
https://embed.tiptap.dev/preview/Nodes/CodeBlockLowlight

View File

@ -1,94 +0,0 @@
---
description: The least code the better, but sometimes you just need multiple lines.
icon: terminal-box-line
---
# CodeBlock
[![Version](https://img.shields.io/npm/v/@tiptap/extension-code-block.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-code-block)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-code-block.svg)](https://npmcharts.com/compare/@tiptap/extension-code-block?minimal=true)
With the CodeBlock extension you can add fenced code blocks to your documents. Itll wrap the code in `<pre>` and `<code>` HTML tags.
Type <code>&grave;&grave;&grave;&nbsp;</code> (three backticks and a space) or <code>&Tilde;&Tilde;&Tilde;&nbsp;</code> (three tildes and a space) and a code block is instantly added for you. You can even specify the language, try writing <code>&grave;&grave;&grave;css&nbsp;</code>. That should add a `language-css` class to the `<code>`-tag.
::: warning No syntax highlighting
The CodeBlock extension doesnt come with styling and has no syntax highlighting built-in. Try the [CodeBlockLowlight](/api/nodes/code-block-lowlight) extension if youre looking for code blocks with syntax highlighting.
:::
## Installation
```bash
npm install @tiptap/extension-code-block
```
## Settings
### languageClassPrefix
Adds a prefix to language classes that are applied to code tags.
Default: `'language-'`
```js
CodeBlock.configure({
languageClassPrefix: 'language-',
})
```
### exitOnTripleEnter
Define whether the node should be exited on triple enter.
Default: `true`
```js
CodeBlock.configure({
exitOnTripleEnter: false,
})
```
### exitOnArrowDown
Define whether the node should be exited on arrow down if there is no node after it.
Default: `true`
```js
CodeBlock.configure({
exitOnArrowDown: false,
})
```
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
CodeBlock.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
## Commands
### setCodeBlock()
Wrap content in a code block.
```js
editor.commands.setCodeBlock()
```
### toggleCodeBlock()
Toggle the code block.
```js
editor.commands.toggleCodeBlock()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| --------------- | ----------------------------- | ------------------------- |
| toggleCodeBlock | `Control`&nbsp;`Alt`&nbsp;`C` | `Cmd`&nbsp;`Alt`&nbsp;`C` |
## Source code
[packages/extension-code-block/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-code-block/)
## Usage
https://embed.tiptap.dev/preview/Nodes/CodeBlock

View File

@ -1,27 +0,0 @@
---
description: "Everyone needs it, nobody talks about it: the Document extension."
icon: file-line
---
# Document
[![Version](https://img.shields.io/npm/v/@tiptap/extension-document.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-document)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-document.svg)](https://npmcharts.com/compare/@tiptap/extension-document?minimal=true)
**The `Document` extension is required**, no matter what you build with Tiptap. Its a so called “topNode”, a node thats the home to all other nodes. Think of it like the `<body>` tag for your document.
The node is very tiny though. It defines a name of the node (`doc`), is configured to be a top node (`topNode: true`) and that it can contain multiple other nodes (`block+`). Thats all. But have a look yourself:
:::warning Breaking Change from 1.x → 2.x
Tiptap 1 tried to hide that node from you, but it has always been there. You have to explicitly import it from now on (or use `StarterKit`).
:::
## Installation
```bash
npm install @tiptap/extension-document
```
## Source code
[packages/extension-document/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-document/)
## Usage
https://embed.tiptap.dev/preview/Nodes/Document

View File

@ -1,59 +0,0 @@
---
description: Sometimes we all need a break, even if its just a line break.
icon: text-wrap
---
# HardBreak
[![Version](https://img.shields.io/npm/v/@tiptap/extension-hard-break.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-hard-break)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-hard-break.svg)](https://npmcharts.com/compare/@tiptap/extension-hard-break?minimal=true)
The HardBreak extensions adds support for the `<br>` HTML tag, which forces a line break.
## Installation
```bash
npm install @tiptap/extension-hard-break
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
HardBreak.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
### keepMarks
Decides whether to keep marks after a line break. Based on the `keepOnSplit` option for marks.
Default: `true`
```js
HardBreak.configure({
keepMarks: false,
})
```
## Commands
### setHardBreak()
Add a line break.
```js
editor.commands.setHardBreak()
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| ------------ | ---------------------------------------------- | ------------------------------------------ |
| setHardBreak | `Shift`&nbsp;`Enter`<br>`Control`&nbsp;`Enter` | `Shift`&nbsp;`Enter`<br>`Cmd`&nbsp;`Enter` |
## Source code
[packages/extension-hard-break/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-hard-break/)
## Usage
https://embed.tiptap.dev/preview/Nodes/HardBreak

View File

@ -1,73 +0,0 @@
---
description: Structure the content with headings (comes with 6 different levels or less).
icon: h-1
---
# Heading
[![Version](https://img.shields.io/npm/v/@tiptap/extension-heading.svg?label=version)](https://www.npmjs.com/package/@tiptap/extension-heading)
[![Downloads](https://img.shields.io/npm/dm/@tiptap/extension-heading.svg)](https://npmcharts.com/compare/@tiptap/extension-heading?minimal=true)
The Heading extension adds support for headings of different levels. Headings are rendered with `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>` or `<h6>` HTML tags. By default all six heading levels (or styles) are enabled, but you can pass an array to only allow a few levels. Check the usage example to see how this is done.
Type <code>#&nbsp;</code> at the beginning of a new line and it will magically transform to a heading, same for <code>##&nbsp;</code>, <code>###&nbsp;</code>, <code>####&nbsp;</code>, <code>#####&nbsp;</code> and <code>######&nbsp;</code>.
## Installation
```bash
npm install @tiptap/extension-heading
```
## Settings
### HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
```js
Heading.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})
```
### levels
Specifies which heading levels are supported.
Default: `[1, 2, 3, 4, 5, 6]`
```js
Heading.configure({
levels: [1, 2],
})
```
## Commands
### setHeading()
Creates a heading node with the specified level.
```js
editor.commands.setHeading({ level: 1 })
```
### toggleHeading()
Toggles a heading node with the specified level.
```js
editor.commands.toggleHeading({ level: 1 })
```
## Keyboard shortcuts
| Command | Windows/Linux | macOS |
| --------------------------- | ----------------------------- | ------------------------- |
| toggleHeading({ level: 1 }) | `Control`&nbsp;`Alt`&nbsp;`1` | `Cmd`&nbsp;`Alt`&nbsp;`1` |
| toggleHeading({ level: 2 }) | `Control`&nbsp;`Alt`&nbsp;`2` | `Cmd`&nbsp;`Alt`&nbsp;`2` |
| toggleHeading({ level: 3 }) | `Control`&nbsp;`Alt`&nbsp;`3` | `Cmd`&nbsp;`Alt`&nbsp;`3` |
| toggleHeading({ level: 4 }) | `Control`&nbsp;`Alt`&nbsp;`4` | `Cmd`&nbsp;`Alt`&nbsp;`4` |
| toggleHeading({ level: 5 }) | `Control`&nbsp;`Alt`&nbsp;`5` | `Cmd`&nbsp;`Alt`&nbsp;`5` |
| toggleHeading({ level: 6 }) | `Control`&nbsp;`Alt`&nbsp;`6` | `Cmd`&nbsp;`Alt`&nbsp;`6` |
## Source code
[packages/extension-heading/](https://github.com/ueberdosis/tiptap/blob/main/packages/extension-heading/)
## Usage
https://embed.tiptap.dev/preview/Nodes/Heading

Some files were not shown because too many files have changed in this diff Show More