mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-08-06 13:38:49 +08:00
move history plugin to extension package
This commit is contained in:
parent
bf1a091c94
commit
deb8cb33b0
31
README.md
31
README.md
@ -46,7 +46,7 @@ export default {
|
||||
## Editor Properties
|
||||
|
||||
| **Property** | **Type** | **Default** | **Description** |
|
||||
| --- | :---: | :---: | --- |
|
||||
| --- | :---: | :---: | --- |
|
||||
| `editable` | `Boolean` | `true` | When set to `false` the editor is read-only. |
|
||||
| `doc` | `Object` | `null` | The editor state object used by Prosemirror. You can also pass HTML to the `content` slot. When used both, the `content` slot will be ignored. |
|
||||
| `extensions` | `Array` | `[]` | A list of extensions used, by the editor. This can be `Nodes`, `Marks` or `Plugins`. |
|
||||
@ -56,7 +56,7 @@ export default {
|
||||
|
||||
By default the editor will only support some boring paragraphs. Other nodes and marks are available as **extensions**. There is a package called `tiptap-extensions` with the most basic nodes, marks and plugins.
|
||||
|
||||
### Available Extensions
|
||||
### Available Extensions
|
||||
|
||||
```vue
|
||||
<template>
|
||||
@ -84,6 +84,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -106,6 +107,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
@ -113,12 +115,12 @@ export default {
|
||||
</script>
|
||||
```
|
||||
|
||||
### Create Custom Extensions
|
||||
### Create Custom Extensions
|
||||
|
||||
The most powerful feature of tiptap is that you can create you own extensions. There are 3 basic types of extensions.
|
||||
|
||||
| **Type** | **Description** |
|
||||
| --- | --- |
|
||||
| --- | --- |
|
||||
| `Extension` | The most basic type. It's useful to register some [Prosemirror plugins](https://prosemirror.net/docs/guide/) or some input rules. |
|
||||
| `Node` | Add a custom node. Nodes are basically block elements like a headline or a paragraph. |
|
||||
| `Mark` | Add a custom mark. Marks are used to add extra styling or other information to inline content like a strong tag or links. |
|
||||
@ -126,16 +128,17 @@ The most powerful feature of tiptap is that you can create you own extensions. T
|
||||
### Extension Class
|
||||
|
||||
| **Method** | **Type** | **Default** | **Description** |
|
||||
| --- | :---: | :---: | --- |
|
||||
| --- | :---: | :---: | --- |
|
||||
| `get name()` | `String` | `null` | Define a name for your extension. |
|
||||
| `get defaultOptions()` | `Object` | `{}` | Define some default options. The options are available as `this.$options`. |
|
||||
| `get plugins()` | `Array` | `[]` | Define a list of [Prosemirror plugins](https://prosemirror.net/docs/guide/). |
|
||||
| `get inputRules()` | `Array` | `[]` | Define a list of input rules. |
|
||||
| `keys({ schema })` | `Object` | `null` | Define some keybindings. |
|
||||
| `inputRules({ schema })` | `Array` | `[]` | Define a list of input rules. |
|
||||
|
||||
### Node|Mark Class
|
||||
|
||||
| **Method** | **Type** | **Default** | **Description** |
|
||||
| --- | :---: | :---: | --- |
|
||||
| --- | :---: | :---: | --- |
|
||||
| `get name()` | `String` | `null` | Define a name for your node or mark. |
|
||||
| `get defaultOptions()` | `Object` | `{}` | Define some default options. The options are available as `this.$options`. |
|
||||
| `get schema()` | `Object` | `null` | Define a [schema](https://prosemirror.net/docs/guide/#schema). |
|
||||
@ -154,12 +157,12 @@ import { Node } from 'tiptap'
|
||||
import { wrappingInputRule, setBlockType, wrapIn } from 'tiptap-commands'
|
||||
|
||||
export default class BlockquoteNode extends Node {
|
||||
|
||||
|
||||
// choose a unique name
|
||||
get name() {
|
||||
return 'blockquote'
|
||||
}
|
||||
|
||||
|
||||
// the prosemirror schema object
|
||||
// take a look at https://prosemirror.net/docs/guide/#schema for a detailed explanation
|
||||
get schema() {
|
||||
@ -179,14 +182,14 @@ export default class BlockquoteNode extends Node {
|
||||
toDOM: () => ['blockquote', { class: 'awesome-blockquote' }, 0],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this command will be called from menus to add a blockquote
|
||||
// `type` is the prosemirror schema object for this blockquote
|
||||
// `schema` is a collection of all registered nodes and marks
|
||||
command({ type, schema }) {
|
||||
return wrapIn(type)
|
||||
}
|
||||
|
||||
|
||||
// here you can register some shortcuts
|
||||
// in this case you can create a blockquote with `ctrl` + `>`
|
||||
keys({ type }) {
|
||||
@ -194,7 +197,7 @@ export default class BlockquoteNode extends Node {
|
||||
'Ctrl->': wrapIn(type),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// a blockquote will be created when you are on a new line and type `>` followed by a space
|
||||
inputRules({ type }) {
|
||||
return [
|
||||
@ -242,7 +245,7 @@ export default class IframeNode extends Node {
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// return a vue component
|
||||
// this can be an object or an imported component
|
||||
get view() {
|
||||
@ -261,7 +264,7 @@ export default class IframeNode extends Node {
|
||||
methods: {
|
||||
onChange(event) {
|
||||
this.url = event.target.value
|
||||
|
||||
|
||||
// update the iframe url
|
||||
this.updateAttrs({
|
||||
src: this.url,
|
||||
|
@ -132,6 +132,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -155,6 +156,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -33,6 +33,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
import Iframe from './Iframe.js'
|
||||
|
||||
@ -57,6 +58,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
// custom extension
|
||||
new Iframe(),
|
||||
],
|
||||
|
@ -118,6 +118,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -141,6 +142,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -53,6 +53,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -76,6 +77,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
linkUrl: null,
|
||||
linkMenuIsActive: false,
|
||||
|
@ -35,6 +35,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -58,6 +59,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -62,6 +62,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -85,6 +86,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -55,6 +56,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -84,6 +84,7 @@ import {
|
||||
Code,
|
||||
Italic,
|
||||
Link,
|
||||
History,
|
||||
} from 'tiptap-extensions'
|
||||
|
||||
export default {
|
||||
@ -107,6 +108,7 @@ export default {
|
||||
new Code(),
|
||||
new Italic(),
|
||||
new Link(),
|
||||
new History(),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -20,6 +20,7 @@
|
||||
"url": "https://github.com/heyscrumpy/tiptap/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"prosemirror-history": "^1.0.2",
|
||||
"tiptap": "^0.5.1",
|
||||
"tiptap-commands": "^0.2.0"
|
||||
}
|
||||
|
30
packages/tiptap-extensions/src/extensions/History.js
Normal file
30
packages/tiptap-extensions/src/extensions/History.js
Normal file
@ -0,0 +1,30 @@
|
||||
import { Extension } from 'tiptap'
|
||||
import { history, undo, redo } from 'prosemirror-history'
|
||||
|
||||
export default class HistoryExtension extends Extension {
|
||||
|
||||
get name() {
|
||||
return 'history'
|
||||
}
|
||||
|
||||
keys() {
|
||||
const isMac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false
|
||||
const keymap = {
|
||||
'Mod-z': undo,
|
||||
'Shift-Mod-z': redo,
|
||||
}
|
||||
|
||||
if (!isMac) {
|
||||
keymap['Mod-y'] = redo
|
||||
}
|
||||
|
||||
return keymap
|
||||
}
|
||||
|
||||
get plugins() {
|
||||
return [
|
||||
history(),
|
||||
]
|
||||
}
|
||||
|
||||
}
|
@ -12,3 +12,5 @@ export { default as Bold } from './marks/Bold'
|
||||
export { default as Code } from './marks/Code'
|
||||
export { default as Italic } from './marks/Italic'
|
||||
export { default as Link } from './marks/Link'
|
||||
|
||||
export { default as History } from './extensions/History'
|
||||
|
@ -26,7 +26,6 @@
|
||||
"dependencies": {
|
||||
"prosemirror-commands": "^1.0.7",
|
||||
"prosemirror-gapcursor": "^1.0.2",
|
||||
"prosemirror-history": "^1.0.2",
|
||||
"prosemirror-inputrules": "^1.0.1",
|
||||
"prosemirror-keymap": "^1.0.1",
|
||||
"prosemirror-model": "^1.5.0",
|
||||
|
@ -2,7 +2,6 @@ import { EditorState, Plugin } from 'prosemirror-state'
|
||||
import { EditorView } from 'prosemirror-view'
|
||||
import { Schema, DOMParser } from 'prosemirror-model'
|
||||
import { gapCursor } from 'prosemirror-gapcursor'
|
||||
import { history } from 'prosemirror-history'
|
||||
import { keymap } from 'prosemirror-keymap'
|
||||
import { baseKeymap } from 'prosemirror-commands'
|
||||
import { inputRules } from 'prosemirror-inputrules'
|
||||
@ -165,7 +164,6 @@ export default {
|
||||
keymap(builtInKeymap),
|
||||
keymap(baseKeymap),
|
||||
gapCursor(),
|
||||
history(),
|
||||
new Plugin({
|
||||
props: {
|
||||
editable: () => this.editable,
|
||||
|
@ -35,6 +35,7 @@ export default class ExtensionManager {
|
||||
|
||||
get views() {
|
||||
return this.extensions
|
||||
.filter(extension => ['node', 'mark'].includes(extension.type))
|
||||
.filter(extension => extension.view)
|
||||
.reduce((views, { name, view }) => ({
|
||||
...views,
|
||||
@ -43,30 +44,60 @@ export default class ExtensionManager {
|
||||
}
|
||||
|
||||
keymaps({ schema }) {
|
||||
return this.extensions
|
||||
const extensionKeymaps = this.extensions
|
||||
.filter(extension => ['extension'].includes(extension.type))
|
||||
.filter(extension => extension.keys)
|
||||
.map(extension => extension.keys({ schema }))
|
||||
|
||||
const nodeMarkKeymaps = this.extensions
|
||||
.filter(extension => ['node', 'mark'].includes(extension.type))
|
||||
.filter(extension => extension.keys)
|
||||
.map(extension => extension.keys({
|
||||
type: schema[`${extension.type}s`][extension.name],
|
||||
schema,
|
||||
}))
|
||||
.map(keys => keymap(keys))
|
||||
|
||||
return [
|
||||
...extensionKeymaps,
|
||||
...nodeMarkKeymaps,
|
||||
].map(keys => keymap(keys))
|
||||
|
||||
// return this.extensions
|
||||
// .filter(extension => ['node', 'mark'].includes(extension.type))
|
||||
// .filter(extension => extension.keys)
|
||||
// .map(extension => extension.keys({
|
||||
// type: schema[`${extension.type}s`][extension.name],
|
||||
// schema,
|
||||
// }))
|
||||
// .map(keys => keymap(keys))
|
||||
}
|
||||
|
||||
inputRules({ schema }) {
|
||||
return this.extensions
|
||||
const extensionInputRules = this.extensions
|
||||
.filter(extension => ['extension'].includes(extension.type))
|
||||
.filter(extension => extension.inputRules)
|
||||
.map(extension => extension.inputRules({ schema }))
|
||||
|
||||
const nodeMarkInputRules = this.extensions
|
||||
.filter(extension => ['node', 'mark'].includes(extension.type))
|
||||
.filter(extension => extension.inputRules)
|
||||
.map(extension => extension.inputRules({
|
||||
type: schema[`${extension.type}s`][extension.name],
|
||||
schema,
|
||||
}))
|
||||
.reduce((allInputRules, inputRules) => ([
|
||||
...allInputRules,
|
||||
...inputRules,
|
||||
]), [])
|
||||
|
||||
return [
|
||||
...extensionInputRules,
|
||||
...nodeMarkInputRules,
|
||||
].reduce((allInputRules, inputRules) => ([
|
||||
...allInputRules,
|
||||
...inputRules,
|
||||
]), [])
|
||||
}
|
||||
|
||||
commands({ schema, view }) {
|
||||
return this.extensions
|
||||
.filter(extension => ['node', 'mark'].includes(extension.type))
|
||||
.filter(extension => extension.command)
|
||||
.reduce((commands, { name, type, command }) => ({
|
||||
...commands,
|
||||
|
@ -1,18 +1,10 @@
|
||||
import { lift, selectParentNode } from 'prosemirror-commands'
|
||||
import { undo, redo } from 'prosemirror-history'
|
||||
import { undoInputRule } from 'prosemirror-inputrules'
|
||||
import isMac from './isMac'
|
||||
|
||||
const keymap = {
|
||||
'Mod-z': undo,
|
||||
'Shift-Mod-z': undo,
|
||||
'Mod-BracketLeft': lift,
|
||||
Backspace: undoInputRule,
|
||||
Escape: selectParentNode,
|
||||
}
|
||||
|
||||
if (!isMac) {
|
||||
keymap['Mod-y'] = redo
|
||||
}
|
||||
|
||||
export default keymap
|
||||
|
@ -27,4 +27,8 @@ export default class Extension {
|
||||
return []
|
||||
}
|
||||
|
||||
keys() {
|
||||
return {}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,5 @@ export { default as buildMenuActions } from './buildMenuActions'
|
||||
export { default as builtInKeymap } from './builtInKeymap'
|
||||
export { default as ComponentView } from './ComponentView'
|
||||
export { default as initNodeViews } from './initNodeViews'
|
||||
export { default as isMac } from './isMac'
|
||||
export { default as menuBubble } from './menuBubble'
|
||||
export { default as ExtensionManager } from './ExtensionManager'
|
||||
|
@ -1 +0,0 @@
|
||||
export default typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false
|
@ -22,8 +22,4 @@ export default class Mark extends Extension {
|
||||
return () => {}
|
||||
}
|
||||
|
||||
keys() {
|
||||
return {}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,8 +22,4 @@ export default class Node extends Extension {
|
||||
return () => {}
|
||||
}
|
||||
|
||||
keys() {
|
||||
return {}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user