Merge branch 'main' of https://github.com/ueberdosis/tiptap into docs/remove-gridsome
# Conflicts: # docs/experiments/collaboration-annotation.md # docs/experiments/global-drag-handle.md
This commit is contained in:
@@ -8,8 +8,6 @@ tableOfContents: true
|
||||
We need your support to maintain, update, support and develop tiptap. If you’re waiting for progress here, [become a sponsor and fund our work](/sponsor).
|
||||
:::
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
We strive to make tiptap accessible to everyone, but to be honest, there’s not much work done now. From our current understanding, that’s what needs to be done:
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Collaborative editing
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
Real-time collaboration, syncing between different devices and working offline used to be hard. We provide everything you need to keep everything in sync, conflict-free with the power of [Y.js](https://github.com/yjs/yjs). The following guide explains all things to take into account when you consider to make tiptap collaborative. Don’t worry, a production-grade setup doesn’t require much code.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Configuration
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
For most cases it’s enough to say where tiptap should be rendered (`element`), what functionalities you want to enable (`extensions`) and what the initial document should be (`content`).
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Custom extensions
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
One of the strengths of tiptap is its extendability. You don’t depend on the provided extensions, it is intended to extend the editor to your liking.
|
||||
|
||||
@@ -304,6 +302,45 @@ This looks for `<strong>` and `<b>` tags, and any HTML tag with an inline style
|
||||
|
||||
As you can see, you can optionally pass a `getAttrs` callback, to add more complex checks, for example for specific HTML attributes. The callback gets passed the HTML DOM node, except when checking for the `style` attribute, then it’s the value.
|
||||
|
||||
#### Using getAttrs
|
||||
The `getAttrs` function you’ve probably noticed in the example has two purposes:
|
||||
|
||||
1. Check the HTML attributes to decide whether a rule matches (and a mark or node is created from that HTML). When the function returns `false`, it’s not matching.
|
||||
2. Get the DOM Element and use the HTML attributes to set your mark or node attributes accordingly:
|
||||
|
||||
```js
|
||||
parseHTML() {
|
||||
return [
|
||||
{
|
||||
tag: 'span',
|
||||
getAttrs: element => {
|
||||
// Check if the element has an attribute
|
||||
element.hasAttribute('style')
|
||||
// Get an inline style
|
||||
element.style.color
|
||||
// Get a specific attribute
|
||||
element.getAttribute('data-color')
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
You can return an object with the attribute as the key and the parsed value to set your mark or node attribute. We would recommend to use the `parseHTML` inside `addAttributes()`, though. That will keep your code cleaner.
|
||||
|
||||
```js
|
||||
addAttributes() {
|
||||
return {
|
||||
color: {
|
||||
// Set the color attribute according to the value of the `data-color` attribute
|
||||
parseHTML: element => element.getAttribute('data-color'),
|
||||
}
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
Read more about `getAttrs` and all other `ParseRule` properties in the [ProseMirror reference](https://prosemirror.net/docs/ref/#model.ParseRule).
|
||||
|
||||
### Commands
|
||||
```js
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
@@ -312,7 +349,7 @@ const CustomParagraph = Paragraph.extend({
|
||||
addCommands() {
|
||||
return {
|
||||
paragraph: () => ({ commands }) => {
|
||||
return commands.toggleNode('paragraph', 'paragraph')
|
||||
return commands.setNode('paragraph')
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -489,14 +526,14 @@ export const EventHandler = Extension.create({
|
||||
```
|
||||
|
||||
### Node views (Advanced)
|
||||
For advanced use cases, where you need to execute JavaScript inside your nodes, for example to render a sophisticated link preview, you need to learn about node views.
|
||||
For advanced use cases, where you need to execute JavaScript inside your nodes, for example to render a sophisticated interface around an image, you need to learn about node views.
|
||||
|
||||
They are really powerful, but also complex. In a nutshell, you need to return a parent DOM element, and a DOM element where the content should be rendered in. Look at the following, simplified example:
|
||||
|
||||
```js
|
||||
import Link from '@tiptap/extension-link'
|
||||
import Image from '@tiptap/extension-image'
|
||||
|
||||
const CustomLink = Link.extend({
|
||||
const CustomImage = Image.extend({
|
||||
addNodeView() {
|
||||
return () => {
|
||||
const container = document.createElement('div')
|
||||
@@ -517,7 +554,7 @@ const CustomLink = Link.extend({
|
||||
})
|
||||
```
|
||||
|
||||
There is a whole lot to learn about node views, so head over to the [dedicated section in our guide about node views](/guide/node-views) for more information. If you’re looking for a real-world example, look at the source code of the [`TaskItem`](/api/nodes/task-item) node. This is using a node view to render the checkboxes.
|
||||
There is a whole lot to learn about node views, so head over to the [dedicated section in our guide about node views](/guide/node-views) for more information. If you are looking for a real-world example, look at the source code of the [`TaskItem`](/api/nodes/task-item) node. This is using a node view to render the checkboxes.
|
||||
|
||||
## Create new extensions
|
||||
You can build your own extensions from scratch and you know what? It’s the same syntax as for extending existing extension described above.
|
||||
|
||||
@@ -4,5 +4,3 @@ tableOfContents: true
|
||||
|
||||
# Overwrite & extend
|
||||
|
||||
## toc
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Create menus
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
tiptap comes very raw, but that’s a good thing. You have full control about the appearance of it.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Interactive node views
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
Node views are the best thing since sliced bread, at least if you are a fan of customization (and bread). With node views you can add interactive nodes to your editor. That can literally be everything. If you can write it in JavaScript, you can use it in your editor.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Examples
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
Node views enable you to fully customize your nodes. We are collecting a few different examples here. Feel free to copy them and start building on them.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Node views with JavaScript
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
Using frameworks like Vue or React can feel too complex, if you’re used to work without those two. Good news: You can use Vanilla JavaScript in your node views. There is just a little bit you need to know, but let’s go through this one by one.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Node views with React
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
Using Vanilla JavaScript can feel complex if you are used to work in React. Good news: You can use regular React components in your node views, too. There is just a little bit you need to know, but let’s go through this one by one.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Node views with Vue
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
Using Vanilla JavaScript can feel complex if you are used to work in Vue. Good news: You can use regular Vue components in your node views, too. There is just a little bit you need to know, but let’s go through this one by one.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Output
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
You can store your content as a JSON object or as a good old HTML string. Both work fine. And of course, you can pass both formats to the editor to restore your content. Here is an interactive example, that exports the content as HTML and JSON when the document is changed:
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Styling
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
tiptap is headless, that means there is no styling provided. That also means, you are in full control of how your editor looks. The following methods allow you to apply custom styles to the editor.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ tableOfContents: true
|
||||
|
||||
# Working with TypeScript
|
||||
|
||||
## toc
|
||||
|
||||
## Introduction
|
||||
The whole tiptap is code base is written in TypeScript. If you haven’t heard of it or never used it, no worries. You don’t have to.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user