The headless rich text editor framework for web artisans.
Go to file
Philipp Kühn e27735bba8 Publish
- tiptap-commands@0.2.0
 - tiptap-extensions@0.2.0
 - tiptap@0.5.0
2018-08-25 00:07:34 +02:00
build remove tiptap-models 2018-08-23 22:44:47 +02:00
examples add a logo 2018-08-24 23:25:36 +02:00
packages Publish 2018-08-25 00:07:34 +02:00
.eslintrc.js initial commit 2018-08-20 23:02:21 +02:00
.gitignore remove docs from gitignore 2018-08-23 11:36:14 +02:00
CONTRIBUTING.md Create CONTRIBUTING.md 2018-08-21 10:12:56 +02:00
lerna.json use independent mode of lerna 2018-08-23 17:24:40 +02:00
LICENSE.md Rename LICENSE to LICENSE.md 2018-08-21 10:14:37 +02:00
package.json add lerna 2018-08-23 13:38:01 +02:00
README.md add node example to readme 2018-08-24 16:52:42 +02:00
yarn.lock add lerna 2018-08-23 13:38:01 +02:00

tiptap

A renderless and extendable rich-text editor for Vue.js

Package Version Downloads Description
tiptap The core package including the vue component.
tiptap-extensions A collection of some basic extensions for tiptap.
tiptap-commands A collection of commands. These are mostly used for extensions.
tiptap-utils A collection of utility functions.

Examples

To check out some live examples, visit tiptap.scrumpy.io.

Installation

npm install tiptap

Basic Setup

<template>
  <editor>
    <!-- Add HTML to the scoped slot called "content" -->
    <div slot="content" slot-scope="props">
      <p>Hi, I'm just a boring paragraph</p>
    </div>
  </editor>
</template>

<script>
// Import the editor
import { Editor } from 'tiptap'

export default {
  components: {
    Editor,
  },
}
</script>

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.
@update Function undefined This will return the current state of Prosemirror on every change.

Extensions

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

<template>
  <editor :extensions="extensions">
    <div slot="content" slot-scope="props">
      <h1>Yay Headlines!</h1>
      <p>All these <strong>cool tags</strong> are working now.</p>
    </div>
  </editor>
</template>

<script>
import { Editor } from 'tiptap'
import {
  Blockquote,
  BulletList,
  CodeBlock,
  HardBreak,
  Heading,
  ListItem,
  OrderedList,
  TodoItem,
  TodoList,
  Bold,
  Code,
  Italic,
  Link,
} from 'tiptap-extensions'

export default {
  components: {
    Editor,
  },
  data() {
    return {
      extensions: [
        new Blockquote(),
        new BulletList(),
        new CodeBlock(),
        new HardBreak(),
        new Heading({ maxLevel: 3 }),
        new ListItem(),
        new OrderedList(),
        new TodoItem(),
        new TodoList(),
        new Bold(),
        new Code(),
        new Italic(),
        new Link(),
      ],
    }
  },
}
</script>

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 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.

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.
get inputRules() 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.
get view() Object null Define a node view as a vue component.
keys({ type, schema }) Object null Define some keybindings.
command({ type, schema, attrs }) Object null Define a command. This is used for menus to convert to this node or mark.
inputRules({ type, schema }) Array [] Define a list of input rules.
get plugins() Array [] Define a list of Prosemirror plugins.

Create a Node

Let's take a look at a real example. This is basically how the default blockquote node from tiptap-extensions looks like.

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
  get schema() {
    return {
      content: 'block+',
      group: 'block',
      defining: true,
      draggable: false,
      // this rule is for parsing pasted HTML
      // so every blockquote tag will be converted to this blockquote node
      parseDOM: [
        { tag: 'blockquote' },
      ],
      // this is how this node will be rendered
      // in this case a blockquote tag with a class called 'awesome-blockquote' will be rendered
      // the '0' stands for its content inside
      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 }) {
    return {
      'Ctrl->': wrapIn(type),
    }
  }
  
  // a blockquote will be created when you are on a new line and type '>' followed by a space
  inputRules({ type }) {
    return [
      wrappingInputRule(/^\s*>\s$/, type),
    ]
  }

}

Create a Node as a Vue Component

For a live example you can take a look at the embed example.

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.