restructure the content, improve a lot

This commit is contained in:
Hans Pagel
2020-09-25 22:22:44 +02:00
parent 4a508fbf2b
commit a8c6c686d8
12 changed files with 218 additions and 230 deletions

View File

@@ -1,57 +1,66 @@
# Events
Events are a great way to run code when the editor has been initialized, the content has changed, the editor is in focus or the editor isnt in focus anymore. There are two ways to add code that is executed at those events:
The editor fires a few different events that you can hook into. There are two ways to register event listeners:
## Option 1: Hook into events
Hooks can be assigned to the editor on initialization. Pass a function that gets called in case of those events.
## Option 1: Right-away
You can define your event listeners on a new editor instance right-away:
```js
const editor = new Editor({
onInit: () => {
// the editor is ready
// The editor is ready.
},
onUpdate: () => {
// the content has been changed
// The content has changed.
},
onFocus: () => {
// The editor is focused.
},
onBlur: () => {
// The editor isnt focused anymore.
},
onTransaction: ({ transaction }) => {
// The editor state has changed.
},
})
```
## Option 2: Listen for events
You can even register event listeners later. Here is the same example with event listeners:
## Option 2: Later
Or you can register your event listeners on a running editor instance:
```js
const editor = new Editor({
// …
})
editor.on('init', () => {
// the editor is ready
})
// The editor is ready.
}
editor.on('update', () => {
// the content has been changed
})
// The content has changed.
}
editor.on('focus', () => {
// The editor is focused.
}
editor.on('blur', () => {
// The editor isnt focused anymore.
}
editor.on('transaction', ({ transaction }) => {
// The editor state has changed.
}
```
### 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 callback = () => {
// the content has been changed
const onUpdate = () => {
// The content has changed.
}
editor.on('update', callback)
editor.off('update', callback)
// Bind …
editor.on('update', onUpdate)
// … and unbind.
editor.off('update', onUpdate)
```
## List of events
| Event | Description | Parameters |
| ------------- | ----------------------------- | ----------------- |
| `blur` | Editor isnt focused anymore. | `{ event }` |
| `focus` | Editor is in focus. | `{ event }` |
| `init` | Editor has been initialized. | *None* |
| `transaction` | State has changed. | `{ transaction }` |
| `update` | Content has changed. | *None* |
:::info List of hooks
The according hooks are called `onBlur`, `onFocus`, `onInit`, `onUpdate` and `onTransaction`.
:::

View File

@@ -36,4 +36,4 @@ This extension doesnt bind a specific keyboard shortcut. You would probably o
[packages/extension-link/](https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-link/)
## Usage
<demo name="Extensions/Link" highlight="3-8,19,38,52" />
<demo name="Extensions/Link" highlight="3-8,19,38,55" />

View File

@@ -1,15 +1,10 @@
# Overview
tiptap is a friendly wrapper around [ProseMirror](https://ProseMirror.net).
* tiptap is a friendly wrapped around ProseMirror.
* 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.
* 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](/api/extensions) add functionality like nodes, marks and/or commands to the editor.
* A huge amount of commands are bound to common [keyboard shortcuts](/api/keyboard-shortcuts).
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.
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](/api/extensions) add functionality like nodes, marks and/or commands to the editor. A huge amount of commands are bound to common [keyboard shortcuts](/api/keyboard-shortcuts).
All of those concepts are explained in detail on the following pages.

View File

@@ -77,3 +77,65 @@ class Text extends Node {
*Nodes* are like blocks of content, for example paragraphs, headlines, code blocks, blockquotes and many more.
*Marks* can apply a different style to specific parts of text inside a *Node*. Thats the case for **bold**, *italic* or ~~striked~~ text. [Links](#) are *Marks*, too.
## Get the underlying ProseMirror schema
There are a few use cases where you need to work with the underlying schema. Youll need that if youre using the tiptap collaborative text editing features or if you want to manually render your content as HTML.
### Option 1: With an Editor
If you need this on the client side and need an editor instance anyway, its available through the editor:
```js
import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
const editor = new Editor({
extensions: [
Document(),
Paragraph(),
Text(),
// add more extensions here
])
})
const schema = editor.schema
```
### Option 2: Without an Editor
If you just want to have the schema *without* initializing an actual editor, you can use the `getSchema` helper function. It needs an array of available extensions and conveniently generates a ProseMirror schema for you:
```js
import { getSchema } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
const schema = getSchema([
Document(),
Paragraph(),
Text(),
// add more extensions here
])
```
## Generate HTML from ProseMirror JSON
If you need to render the content on the server side, e. g. for a blog post that was written with tiptap, youll probably need a way to do just that without an actual editor instance.
Thats what `generateHtml()` is for. Its a utility function that renders HTML without an actual editor instance.
:::warning Work in progress
Currently, that works only in the browser (client side), but we plan to bring this to Node.js (to use it on the server side).
:::
<demo name="Api/Schema/GenerateHtml" highlight="6,29-33"/>
### Converting JSON<>HTML with PHP
We needed to do the same thing in PHP at some point, so we published libraries to convert ProseMirror JSON to HTML and vice-versa:
* [ueberdosis/prosemirror-php](https://github.com/ueberdosis/prosemirror-php) (PHP)
* [ueberdosis/prosemirror-to-html](https://github.com/ueberdosis/prosemirror-to-html) (PHP)
* [ueberdosis/html-to-prosemirror](https://github.com/ueberdosis/html-to-prosemirror) (PHP)

View File

@@ -1,19 +0,0 @@
# Generate HTML from ProseMirror JSON
If you need to render the content on the server side, e. g. for a blog post that was written with tiptap, youll probably need a way to do just that without an actual editor instance.
Thats what `generateHtml()` is for. Its a utility function that renders HTML without an actual editor instance.
:::warning Work in progress
Currently, that works only in the browser (client side), but we plan to bring this to Node.js (to use it on the server side).
:::
<demo name="Api/Schema/GenerateHtml" highlight="6,29-33"/>
## Converting JSON<>HTML with PHP
We needed to do the same thing in PHP at some point, so we published libraries to convert ProseMirror JSON to HTML and vice-versa:
* [ueberdosis/prosemirror-php](https://github.com/ueberdosis/prosemirror-php) (PHP)
* [ueberdosis/prosemirror-to-html](https://github.com/ueberdosis/prosemirror-to-html) (PHP)
* [ueberdosis/html-to-prosemirror](https://github.com/ueberdosis/html-to-prosemirror) (PHP)

View File

@@ -1,41 +0,0 @@
# Get the underlying ProseMirror schema
There are a few use cases where you need to work with the underlying schema. Youll need that if youre using the tiptap collaborative text editing features or if you want to manually render your content as HTML.
## Option 1: With an Editor
If you need this on the client side and need an editor instance anyway, its available through the editor:
```js
import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
const editor = new Editor({
extensions: [
Document(),
Paragraph(),
Text(),
// add more extensions here
])
})
const schema = editor.schema
```
## Option 2: Without an Editor
If you just want to have the schema *without* initializing an actual editor, you can use the `getSchema` helper function. It needs an array of available extensions and conveniently generates a ProseMirror schema for you:
```js
import { getSchema } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
const schema = getSchema([
Document(),
Paragraph(),
Text(),
// add more extensions here
])
```

View File

@@ -1,3 +1,3 @@
# Links
<demo name="Examples/Links" />
<demo name="Examples/Links" highlight="3-8,19,38,55" />

View File

@@ -25,8 +25,114 @@ new Editor({
})
```
You can overwrite every aspect of an existing extension. [Read more about that here.](/guide/custom-extensions/overwrite-defaults)
You can overwrite every aspect of an existing extension:
### Name
```js
import Document from '@tiptap/extension-document'
const CustomDocument = Document()
.name('doc')
.create()
```
### Settings
```js
import Heading from '@tiptap/extension-heading'
const CustomHeading = Heading()
.defaults({
levels: [1, 2, 3],
class: 'my-custom-heading',
})
.create()
```
### Schema
```js
import Code from '@tiptap/extension-code'
const CustomCode = Code()
.schema(() => ({
excludes: '_',
parseDOM: [
{ tag: 'code' },
],
toDOM: () => ['code', { 'data-attribute': 'foobar' }, 0],
}))
.create()
```
### Commands
```js
import Paragraph from '@tiptap/extension-paragraph'
const CustomParagraph = Paragraph()
.commands(() => ({
paragraph: () => ({ commands }) => {
return commands.toggleBlockType(name, 'paragraph')
},
}))
.create()
```
### Keyboard shortcuts
```js
import BulletList from '@tiptap/extension-bullet-list'
const CustomBulletList = BulletList()
.keys(({ editor }) => ({
'Mod-l': () => editor.bulletList(),
}))
.create()
```
### Input rules
```js
import Strike from '@tiptap/extension-strike'
import { markInputRule } from '@tiptap/core'
const inputRegex = /(?:^|\s)((?:~)((?:[^~]+))(?:~))$/gm
const CustomStrike = Strike()
.inputRules(({ type }) => [
markInputRule(inputRegex, type),
])
.create()
```
### Paste rules
```js
import Underline from '@tiptap/extension-underline'
import { markPasteRule } from '@tiptap/core'
const pasteRegex = /(?:^|\s)((?:~)((?:[^~]+))(?:~))$/gm
const CustomUnderline = Underline()
.pasteRules(({ type }) => [
markPasteRule(pasteRegex, type),
])
.create()
```
## Option 2: Extend existing extensions
## Option 3: Start from scratch
### 1. Read the documentation
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.
### 2. Have a look at existing extensions
### 3. Get started
### 4. Ask questions
### 5. Publish a community extension

View File

@@ -1,96 +0,0 @@
# Change defaults
## Name
```js
import Document from '@tiptap/extension-document'
const CustomDocument = Document()
.name('doc')
.create()
```
## Settings
```js
import Heading from '@tiptap/extension-heading'
const CustomHeading = Heading()
.defaults({
levels: [1, 2, 3],
class: 'my-custom-heading',
})
.create()
```
## Schema
```js
import Code from '@tiptap/extension-code'
const CustomCode = Code()
.schema(() => ({
excludes: '_',
parseDOM: [
{ tag: 'code' },
],
toDOM: () => ['code', { 'data-attribute': 'foobar' }, 0],
}))
.create()
```
## Commands
```js
import Paragraph from '@tiptap/extension-paragraph'
const CustomParagraph = Paragraph()
.commands(() => ({
paragraph: () => ({ commands }) => {
return commands.toggleBlockType(name, 'paragraph')
},
}))
.create()
```
## Keyboard shortcuts
```js
import BulletList from '@tiptap/extension-bullet-list'
const CustomBulletList = BulletList()
.keys(({ editor }) => ({
'Mod-l': () => editor.bulletList(),
}))
.create()
```
## Input rules
```js
import Strike from '@tiptap/extension-strike'
import { markInputRule } from '@tiptap/core'
const inputRegex = /(?:^|\s)((?:~)((?:[^~]+))(?:~))$/gm
const CustomStrike = Strike()
.inputRules(({ type }) => [
markInputRule(inputRegex, type),
])
.create()
```
## Paste rules
```js
import Underline from '@tiptap/extension-underline'
import { markPasteRule } from '@tiptap/core'
const pasteRegex = /(?:^|\s)((?:~)((?:[^~]+))(?:~))$/gm
const CustomUnderline = Underline()
.pasteRules(({ type }) => [
markPasteRule(pasteRegex, type),
])
.create()
```

View File

@@ -1 +0,0 @@
# Extend existing extensions

View File

@@ -1,12 +0,0 @@
# Start from scratch
## 1. Read the documentation
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.
## 2. Have a look at existing extensions
## 3. Get started
## 4. Ask questions
## 5. Publish a community extension

View File

@@ -88,16 +88,6 @@
link: /guide/store-content
- title: Custom extensions
link: /guide/custom-extensions
items:
- title: Change defaults
link: /guide/custom-extensions/change-defaults
draft: true
- title: Extend extensions
link: /guide/custom-extensions/extend-extensions
draft: true
- title: Start from scratch
link: /guide/custom-extensions/start-from-scratch
draft: true
- title: Use Vue Components
link: /guide/use-vue-components
draft: true
@@ -183,10 +173,5 @@
link: /api/events
- title: Schema
link: /api/schema
items:
- title: Get Schema
link: /api/schema/get-schema
- title: Generate HTML
link: /api/schema/generate-html
- title: Keyboard Shortcuts
link: /api/keyboard-shortcuts