A renderless rich-text editor for Vue.js

Overview

We’re working on tiptap 2. Become a sponsor to get access immediately! Sponsor 💖

tiptap

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

Gitpod Ready-to-Code Version Downloads License Filesize Build Status Sponsor

[FAQ] Should I start to integrate tiptap 1 or wait for tiptap 2?

Good question! tiptap 2 is about to come in the next months and we’re going to provide an upgrade guide for you. Sure, there are a lot of things that will change, but you should be able to refactor everything in an hour so (depending on the size of your project).

The extension API will have a lot of breaking changes. So if you’re up to write a lot of custom extensions, expect to rewrite them for tiptap 2. You’ll likely reuse all the single parts (schema, inputRules, pasteRules, keyboard shortcuts …), but the API to register them will be different.

For the braves: Sponsor us to get access to tiptap 2 and start your project with a fresh breeze of air.

For everyone else: No need to wait for tiptap 2. Start your project, you’ll be able to upgrade in a reasonable amount of time.

Why I built tiptap

I was looking for a text editor for Vue.js and found some solutions that didn't really satisfy me. The editor should be easy to extend and not based on old dependencies such as jQuery. For React there is already a great editor called Slate.js, which impresses with its modularity. I came across Prosemirror and decided to build on it. Prosemirror is a toolkit for building rich-text editors that are already in use at many well-known companies such as Atlassian or New York Times.

What does renderless mean?

With renderless components you'll have (almost) full control over markup and styling. I don't want to tell you what a menu should look like or where it should be rendered in the DOM. That's all up to you. There is also a good article about renderless components by Adam Wathan.

How is the data stored under the hood?

You can save your data as a raw HTML string or can get a JSON-serializable representation of your document. And of course, you can pass these two types back to the editor.

💖 Sponsor the development

Are you using tiptap in production? We need your sponsorship to maintain, update and develop tiptap. Become a Sponsor now!

Examples

To check out some live examples, visit tiptap.dev.

Installation

npm install tiptap

or

yarn add tiptap

Basic Setup

<template>
  <editor-content :editor="editor" />
</template>

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

export default {
  components: {
    EditorContent,
  },
  data() {
    return {
      editor: null,
    }
  },
  mounted() {
    this.editor = new Editor({
      content: '<p>This is just a boring paragraph</p>',
    })
  },
  beforeDestroy() {
    this.editor.destroy()
  },
}
</script>

Editor Properties

Property Type Default Description
content Object|String 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.
editorProps Object {} A list of Prosemirror editorProps.
editable Boolean true When set to false the editor is read-only.
autoFocus Boolean false Focus the editor on init.
extensions Array [] A list of extensions used, by the editor. This can be Nodes, Marks or Plugins.
useBuiltInExtensions Boolean true By default tiptap adds a Doc, Paragraph and Text node to the Prosemirror schema.
dropCursor Object {} Config for prosemirror-dropcursor.
enableDropCursor Boolean true Option to enable / disable the dropCursor plugin.
enableGapCursor Boolean true Option to enable / disable the gapCursor plugin.
parseOptions Object {} A list of Prosemirror parseOptions.
onInit Function undefined This will return an Object with the current state and view of Prosemirror on init.
onFocus Function undefined This will return an Object with the event and current state and view of Prosemirror on focus.
onBlur Function undefined This will return an Object with the event and current state and view of Prosemirror on blur.
onUpdate Function undefined This will return an Object with the current state of Prosemirror, a getJSON() and getHTML() function and the transaction on every change.

Editor Methods

Method Arguments Description
setContent content, emitUpdate, parseOptions Replace the current content. You can pass an HTML string or a JSON document. emitUpdate defaults to false. parseOptions defaults to those provided in constructor.
clearContent emitUpdate Clears the current content. emitUpdate defaults to false.
setOptions options Overwrites the current editor properties.
registerPlugin plugin, handlePlugins Register a Prosemirror plugin. You can pass a function handlePlugins with parameters (plugin, oldPlugins) to define an order in which newPlugins will be called. handlePlugins defaults to pushing plugin to front of oldPlugins.
getJSON Get the current content as JSON.
getHTML Get the current content as HTML.
focus Focus the editor.
blur Blur the editor.
destroy Destroy the editor.

Components

Name Description
<editor-content /> Here the content will be rendered.
<editor-menu-bar /> Here a menu bar will be rendered.
<editor-menu-bubble /> Here a menu bubble will be rendered.
<editor-floating-menu /> Here a floating menu will be rendered.

EditorMenuBar

The <editor-menu-bar /> component is renderless and will receive some properties through a scoped slot.

Property Type Description
commands Array A list of all commands.
isActive Object An object of functions to check if your selected text is a node or mark. `isActive.{node
getMarkAttrs Function A function to get all mark attributes of your selection.
getNodeAttrs Function A function to get all node attributes of your selection.
focused Boolean Whether the editor is focused.
focus Function A function to focus the editor.

Example

<template>
  <editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
    <div>
      <button :class="{ 'is-active': isActive.bold() }" @click="commands.bold">
        Bold
      </button>
      <button :class="{ 'is-active': isActive.heading({ level: 2 }) }" @click="commands.heading({ level: 2 })">
        H2
      </button>
    </div>
  </editor-menu-bar>
</template>

EditorMenuBubble

The <editor-menu-bubble /> component is renderless and will receive some properties through a scoped slot.

Property Type Description
commands Array A list of all commands.
isActive Object An object of functions to check if your selected text is a node or mark. `isActive.{node
getMarkAttrs Function A function to get all mark attributes of your selection.
getNodeAttrs Function A function to get all node attributes of your selection.
focused Boolean Whether the editor is focused.
focus Function A function to focus the editor.
menu Object An object for positioning your menu.

Example

<template>
  <editor-menu-bubble :editor="editor" v-slot="{ commands, isActive, menu }">
    <div
      :class="{ 'is-active': menu.isActive }"
      :style="`left: ${menu.left}px; bottom: ${menu.bottom}px;`"
    >
      <button :class="{ 'is-active': isActive.bold() }" @click="commands.bold">
        Bold
      </button>
      <button :class="{ 'is-active': isActive.heading({ level: 2 }) }" @click="commands.heading({ level: 2 })">
        H2
      </button>
    </div>
  </editor-menu-bubble>
</template>

EditorFloatingMenu

The <editor-floating-menu /> component is renderless and will receive some properties through a scoped slot.

Property Type Description
commands Array A list of all commands.
isActive Object An object of functions to check if your selected text is a node or mark. `isActive.{node
getMarkAttrs Function A function to get all mark attributes of your selection.
getNodeAttrs Function A function to get all node attributes of your selection.
focused Boolean Whether the editor is focused.
focus Function A function to focus the editor.
menu Object An object for positioning your menu.

Example

<template>
  <editor-floating-menu :editor="editor" v-slot="{ commands, isActive, menu }">
    <div
      :class="{ 'is-active': menu.isActive }"
      :style="`top: ${menu.top}px`"
    >
      <button :class="{ 'is-active': isActive.bold() }" @click="commands.bold">
        Bold
      </button>
      <button :class="{ 'is-active': isActive.heading({ level: 2 }) }" @click="commands.heading({ level: 2 })">
        H2
      </button>
    </div>
  </editor-floating-menu>
</template>

Extensions

By default, the editor will only support 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>
  <div>
    <editor-menu-bar :editor="editor" v-slot="{ commands, isActive }">
        <button :class="{ 'is-active': isActive.bold() }" @click="commands.bold">
          Bold
        </button>
    </editor-menu-bar>
    <editor-content :editor="editor" />
  </div>
</template>

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

export default {
  components: {
    EditorMenuBar,
    EditorContent,
  },
  data() {
    return {
      editor: new Editor({
        extensions: [
          new Blockquote(),
          new CodeBlock(),
          new HardBreak(),
          new Heading({ levels: [1, 2, 3] }),
          new BulletList(),
          new OrderedList(),
          new ListItem(),
          new TodoItem(),
          new TodoList(),
          new Bold(),
          new Code(),
          new Italic(),
          new Link(),
          new Strike(),
          new Underline(),
          new History(),
        ],
        content: `
          <h1>Yay Headlines!</h1>
          <p>All these <strong>cool tags</strong> are working now.</p>
        `,
      }),
    }
  },
  beforeDestroy() {
    this.editor.destroy()
  },
}
</script>

Create Custom Extensions

The most powerful feature of tiptap is that you can create your own extensions. There are 3 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 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.
keys({ schema }) Object null Define some keybindings.
commands({ schema, attrs }) Object null Define a command.
inputRules({ schema }) Array [] Define a list of input rules.
pasteRules({ schema }) Array [] Define a list of paste rules.
get update() Function undefined Called when options of extension are changed via editor.extensions.options

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.
commands({ type, schema, attrs }) Object null Define a command. For example this is used for menus to convert to this node or mark.
inputRules({ type, schema }) Array [] Define a list of input rules.
pasteRules({ type, schema }) Array [] Define a list of paste 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, toggleWrap } 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() {
    return {
      content: 'block+',
      group: 'block',
      defining: true,
      draggable: false,
      // define how the editor will detect your node from pasted HTML
      // 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 text 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
  commands({ type, schema }) {
    return () => toggleWrap(type)
  }

  // here you can register some shortcuts
  // in this case you can create a blockquote with `ctrl` + `>`
  keys({ type }) {
    return {
      'Ctrl->': toggleWrap(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

The real power of the nodes comes in combination with Vue components. Let us build an iframe node, where you can change its URL (this can also be found in our examples).

import { Node } from 'tiptap'

export default class IframeNode extends Node {

  get name() {
    return 'iframe'
  }

  get schema() {
    return {
      // here you have to specify all values that can be stored in this node
      attrs: {
        src: {
          default: null,
        },
      },
      group: 'block',
      selectable: false,
      // parseDOM and toDOM is still required to make copy and paste work
      parseDOM: [{
        tag: 'iframe',
        getAttrs: dom => ({
          src: dom.getAttribute('src'),
        }),
      }],
      toDOM: node => ['iframe', {
        src: node.attrs.src,
        frameborder: 0,
        allowfullscreen: 'true',
      }],
    }
  }

  // return a vue component
  // this can be an object or an imported component
  get view() {
    return {
      // there are some props available
      // `node` is a Prosemirror Node Object
      // `updateAttrs` is a function to update attributes defined in `schema`
      // `view` is the ProseMirror view instance
      // `options` is an array of your extension options
      // `selected` is a boolean which is true when selected
      // `editor` is a reference to the TipTap editor instance
      // `getPos` is a function to retrieve the start position of the node
      // `decorations` is an array of decorations around the node
      props: ['node', 'updateAttrs', 'view'],
      computed: {
        src: {
          get() {
            return this.node.attrs.src
          },
          set(src) {
            // we cannot update `src` itself because `this.node.attrs` is immutable
            this.updateAttrs({
              src,
            })
          },
        },
      },
      template: `
        <div class="iframe">
          <iframe class="iframe__embed" :src="src"></iframe>
          <input class="iframe__input" type="text" v-model="src" v-if="view.editable" />
        </div>
      `,
    }
  }

}

NodeView Prop Types

Prop Type Description
node Object The Prosemirror node object. Common use case is to get node.attrs using a getter on a computed property.
updateAttrs Function A function to update node.attrs defined in schema. Common use case is as setter on a computed property.
view Object The Prosemirror editor view instance.
options Array An array of your extension options.
getPos Function A function that returns the anchored position of the node.
selected Boolean A boolean that is set when the node is or is not selected. Common use case is using watch to see when the view is selected/unselected to do something, such focus an <input> or refocus the editor.

Collaborative editing

Collaborative editing is a complex topic. Luckily, @naept wrote an article about collaborative editing with tiptap and also published two helpful repositories:

Browser Support

Chrome Firefox IE Opera Safari
Last 2 Versions Last 2 Versions Last 2 Versions Last 2 Versions Last 2 Versions

Development Setup

Currently, only Yarn is supported for development because of a feature called workspaces we are using here.

# install dependencies
yarn install

# serve examples at localhost:3000
yarn start

# build dist files for packages
yarn build:packages

# build dist files for examples
yarn build:examples

Contribute using the online one-click setup

You can use Gitpod(a free online VS Code-like IDE) for contributing. With a single click, it will launch a workspace and automatically:

  • clone the tiptap repo.
  • install the dependencies.
  • run yarn run start.

So that anyone interested in contributing can start straight away.

Open in Gitpod

Contributing

Please see CONTRIBUTING for details.

Credits

Related projects

Love our work?

Sponsor us ❤️

License

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

Comments
  • Error: Looks like multiple versions of prosemirror-model were loaded

    Error: Looks like multiple versions of prosemirror-model were loaded

    Describe the bug When using the editor (e.g. using ENTER key) it's not working, and we got error in the console:

    Can not convert <> to a Fragment (looks like multiple versions of prosemirror-model were loaded)
    

    Due to [email protected] and [email protected] loaded simultaneously.

    tiptap-extensions package requires strictly version 1.8.2 and other packages prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.8.1 which resolves to 1.9.0

    Steps to Reproduce / Codesandbox Example Steps to reproduce the behaviour:

    1. install
    "tiptap": "^1.27.1",
    "tiptap-extensions": "^1.29.1"
    

    with Yarn. This will install [email protected] and [email protected].

    1. When using the editor (e.g. using ENTER key) it's not working, and we got error in the console

    Expected behaviour Editor should work, there should be only one prosemirror-model package installed.

    Quick and dirty workaround for users (it's not proper fix!) - use resolutions entry in package.json:

        "resolutions": {
            "prosemirror-model": "1.9.1"
        }
    

    Then remove node_modules, yarn.lock and install packages again.

    bug 
    opened by karol-f 111
  • tiptap v2

    tiptap v2

    First of all I would like to say thank you for the last year. You made tiptap to what it is today – probably the best rich text editor for Vue.js 😛

    Tiptap hits 200K downloads per month now. Incredible!

    However, there is always something to do and a new major version is a good opportunity to tackle some bigger challenges. I would like to say that I have officially started the development of tiptap 2! 🎉

    In this thread I want to show the first new features and keep you up to date for new ideas. Please write your wishes here so that we can discuss them! ✌️

    🏗 Some updates about the project structure

    Move packages to its own organisation

    tiptap -> @tiptap
    

    Split tiptap-extensions into multiple packages

    Splitting the extensions into separate packages has the advantage to better optimize its bundle size. Especially if there are some larger dev-dependencies like hightlight.js for syntax highlighting. It's also easier to release alternative packages like @tiptap/highlight-code-extension and @tiptap/prism-code-extension.

    @tiptap/bold-extension
    @tiptap/italic-extension
    @tiptap/code-extension
    …
    

    Move Vue.js components out of the core

    The Vue components will no longer be part of the core. Maybe I'll also try to release a React package – but I'm not quite sure yet if I want to do this to myself 😅

    @tiptap/core
    @tiptap/vue
    

    Move core extensions out of the core

    So they won't be core extensions anymore. Makes it easier to define custom documents like this.

    @tiptap/document-extension
    @tiptap/paragraph-extension
    @tiptap/text-extension
    

    Create extension collections

    For a better quick start for people who just want to use the full functionality of tiptap, I can imagine putting together collections.

    import extensions from '@tiptap/starter—kit'
    
    new Editor({ extensions })
    

    TypeScript #54

    I see the advantages of TypeScript, so I will try to rewrite tiptap completely in TypeScript.

    Combine landingpage and docs

    The documentation is really awful at the moment. That will change. In my mind there is a guide with integrated demos.

    E2E tests

    At the moment there are just some function tests which is not enough. To provide better stability, I would like to write some E2E tests.

    🔥 New Features

    Chained Commands

    Chain a list of core commands.

    editor
      .focus('end')
      .insertText('at the end')
      .newLine()
      .insertText('new line')
      .toggleBlockNode('heading', { level: 2 })
    

    Or register your own commands.

    editor.registerCommand('log', (next, editor, text) => {
      console.log(text)
      next()
    })
    
    editor.log('hey!')
    // 'hey!'
    

    Commands can be asynchronous too.

    editor.registerCommand('insertUserName', await (next, editor, id) => {
      let response = await fetch(`/api/${id}`);
      let data = await response.json()
      editor.insertText(data.user.name)
      next()
    })
    
    editor.insertUserName(123)
    

    Global node attributes

    Not sure about final syntax for this but basically I want to provide an option to add attributes to multiple nodes or marks at once.

    So instead of repeating attributes (like text-align #180)…

    class Paragraph extends Node {
      schema = {
        attrs: {
          textAlign: {
            default: 'left',
          }
        }
      }
    }
    
    class Heading extends Node {
      schema = {
        attrs: {
          textAlign: {
            default: 'left',
          }
        }
      }
    }
    

    … you can register global attributes.

    editor.registerAttribute(['paragraph', 'heading'], {
      textAlign: {
        default: 'left',
      }
    })
    

    More ideas?

    Comment here and let’s discuss your ideas! I will also go through the existing issues soon and tag with v2 if possible.

    ☠️ Things I'm not gonna do in v2:

    ~~Markdown support~~

    After playing around with ProseMirror and CodeMirror, I absolutely don't see any point in integrating Markdown support. Just use CodeMirror (or something else) and export/import from/to tiptap.

    opened by philippkuehn 103
  • Vue 3 Support

    Vue 3 Support

    I understand Vue 3 support is on the roadmap and you are waiting for Gridsome to support it in order to move the documentation to Vue 3: https://github.com/ueberdosis/tiptap/issues/735#issuecomment-719729347

    I'm using TipTap in a Vue 3 (Ionic) app and so intend to at least port EditorContent but probably also VueRenderer to Vue 3. Has any work been done on this? I seems wasteful to replicate something that may have already been done. Happy to contribute my changes if not.

    One thing that needs to be considered is if TipTap 2 will support both Vue 2 and 3. It seems that most libraries are adding Vue 3 support by having a 'next' branch (this could be tiptap/packages/vue3 rather than a branch) although there is at least one attempt at creating a tool to enable you to have a single codebase that supports both 2 and 3 (https://github.com/antfu/vue-demi).

    opened by samwillis 76
  • Bug after update to 1.19.0 : RangeError: Adding different instances of a keyed plugin (plugin$1)

    Bug after update to 1.19.0 : RangeError: Adding different instances of a keyed plugin (plugin$1)

    I've updated tiptap from v1.8.0 to v1.19.0 and now I have this bug in the console :

    [Vue warn]: Error in data(): "RangeError: Adding different instances of a keyed plugin (plugin$1)"

    The editor does not work anymore.

    bug 
    opened by ligne13 46
  • Recent port of ProseMirror to TypeScript and ProseMirror version bumps (hours ago) break TipTap

    Recent port of ProseMirror to TypeScript and ProseMirror version bumps (hours ago) break TipTap

    What’s the bug you are facing?

    ProseMirror has been recently ported to TypeScript, and a few hours ago ProseMirror lib versions have been bumped.

    Due to TipTap not using fixed dependency versions (for example, in core), when doing a clean install of TipTap now, the new ProseMirror libs are used, and they are incompatible with TipTap on the TypeScript side.

    For example, when compiling something that uses TipTap, I now get typing errors like:

    ERROR: node_modules/@tiptap/core/dist/packages/core/src/Editor.d.ts:95:39 - error TS2315: Type 'Transaction' is not generic.
    
    95     captureTransaction(fn: Function): Transaction<any> | null;
    
    node_modules/@tiptap/core/dist/packages/core/src/NodeView.d.ts:18:9 - error TS2416: Property 'contentDOM' in type 'NodeView<Component, Editor, Options>' is not assignable to the same property in base type 'NodeView'.
      Type 'Element' is missing the following properties from type 'HTMLElement': accessKey, accessKeyLabel, autocapitalize, dir, and 111 more.
    
    18     get contentDOM(): Element | null;
    
    node_modules/@tiptap/core/dist/packages/core/src/helpers/findParentNode.d.ts:8:11 - error TS2315: Type 'Node' is not generic.
    
    8     node: import("prosemirror-model").Node<any>;
    
    node_modules/@tiptap/extension-bubble-menu/dist/packages/extension-bubble-menu/src/bubble-menu-plugin.d.ts:43:76 - error TS2707: Generic type 'Plugin<PluginState>' requires between 0 and 1 type arguments.
    
    43 export declare const BubbleMenuPlugin: (options: BubbleMenuPluginProps) => Plugin<any, any>;
    
    node_modules/@tiptap/extension-table/dist/packages/extension-table/src/utilities/createTable.d.ts:2:129 - error TS2315: Type 'Fragment' is not generic.
    
    2 export declare function createTable(schema: Schema, rowsCount: number, colsCount: number, withHeaderRow: boolean, cellContent?: Fragment<Schema> | ProsemirrorNode<Schema> | Array<ProsemirrorNode<Schema>>): ProsemirrorNode;
    
    node_modules/@tiptap/extension-table/dist/packages/extension-table/src/utilities/createTable.d.ts:2:148 - error TS2315: Type 'Node' is not generic.
    
    2 export declare function createTable(schema: Schema, rowsCount: number, colsCount: number, withHeaderRow: boolean, cellContent?: Fragment<Schema> | ProsemirrorNode<Schema> | Array<ProsemirrorNode<Schema>>): ProsemirrorNode;
    
    
    node_modules/@tiptap/extension-table/dist/packages/extension-table/src/utilities/createTable.d.ts:2:180 - error TS2315: Type 'Node' is not generic.
    
    2 export declare function createTable(schema: Schema, rowsCount: number, colsCount: number, withHeaderRow: boolean, cellContent?: Fragment<Schema> | ProsemirrorNode<Schema> | Array<ProsemirrorNode<Schema>>): ProsemirrorNode;
    

    Here's a screenshot which is perhaps more readable than the above dump:

    image

    This makes a fresh TipTap install completely unusable, for both new users, and existing users who refresh their node_modules.

    Which browser was this experienced in? Are any special extensions installed?

    Not a browser issue, this pertains to the installation/transpilation phase.

    How can we reproduce the bug on our side?

    Do a fresh install of TipTap. I'm using these:

    "@tiptap/core": "2.0.0-beta.176",
    "@tiptap/extension-blockquote": "2.0.0-beta.26",
    "@tiptap/extension-bubble-menu": "2.0.0-beta.56",
    "@tiptap/extension-bullet-list": "2.0.0-beta.26",
    "@tiptap/extension-color": "2.0.0-beta.9",
    "@tiptap/extension-gapcursor": "2.0.0-beta.34",
    "@tiptap/extension-hard-break": "2.0.0-beta.30",
    "@tiptap/extension-highlight": "2.0.0-beta.33",
    "@tiptap/extension-horizontal-rule": "2.0.0-beta.31",
    "@tiptap/extension-image": "2.0.0-beta.27",
    "@tiptap/extension-link": "2.0.0-beta.38",
    "@tiptap/extension-list-item": "2.0.0-beta.20",
    "@tiptap/extension-ordered-list": "2.0.0-beta.27",
    "@tiptap/extension-placeholder": "2.0.0-beta.48",
    "@tiptap/extension-subscript": "2.0.0-beta.10",
    "@tiptap/extension-superscript": "2.0.0-beta.10",
    "@tiptap/extension-table": "2.0.0-beta.49",
    "@tiptap/extension-table-cell": "2.0.0-beta.20",
    "@tiptap/extension-table-header": "2.0.0-beta.22",
    "@tiptap/extension-table-row": "2.0.0-beta.19",
    "@tiptap/extension-text-align": "2.0.0-beta.29",
    "@tiptap/extension-text-style": "2.0.0-beta.23",
    "@tiptap/extension-underline": "2.0.0-beta.23",
    "@tiptap/starter-kit": "2.0.0-beta.185",
    

    Then, instantiate an editor, and transpile that code.

    Can you provide a CodeSandbox?

    N/A

    What did you expect to happen?

    A normal transpilation of the code using TipTap.

    Anything to add? (optional)

    I believe the quick solution to this is to set all ProseMirror dependencies to the last working fixed versions, thus reverting to normal, until there is time for TipTap to catch up with the ProseMirror TypeScript port. The latter will likely take a long time, during which TipTap installs are essentially unusable.

    Did you update your dependencies?

    • [x] Yes, I’ve updated my dependencies to use the latest version of all packages.

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    bug 
    opened by tgv1975 41
  • Markdown input and output

    Markdown input and output

    opened by SebastianEberlein 39
  • Make sure editor is available on first render

    Make sure editor is available on first render

    This is a fix for #2182 - it makes sure that the editor is available on the first render of useEditor in the react package.

    The reason for this fix is that the first render never has an editor and that causes the page's content to jump and flash. First render has no editor, so nothing is rendered. Then the second render has the editor and the WYSIWYG editor is rendered causing all the content on the page to shift down.

    The effect will also re-create the editor if anything in the deps list changes.

    cc @philippkuehn

    opened by ryanto 36
  • Feature request: Add a 'checkLocation' option to the Suggest plugin

    Feature request: Add a 'checkLocation' option to the Suggest plugin

    Currently the suggest plugin triggering is controlled by the char/startOfLine options and so it is triggered in any text node. It would be brilliant If we could limit-to/exclude-from certain nodes.

    Something like this would work:

    // Exclude the suggestions from blockquotes
    checkLocation: (editor) => {
        return !editor.commands.isActive('blockquote')
    }
    

    I'm using it for hashtags and have a node type where hash tags are not supported.

    opened by samwillis 31
  • Collaborative Editing

    Collaborative Editing

    Are there any plans on implementing collaborative editing for this plugin? Any pointers on how to start on this?

    Prosemirror Demo: https://prosemirror.net/examples/collab/#edit-Example Prosemirror Docs: https://prosemirror.net/docs/guide/#collab

    feature request help wanted 
    opened by thomasaull 30
  • MenuBubble: Error in v-on handler:

    MenuBubble: Error in v-on handler: "IndexSizeError: Failed to execute 'setStart' on 'Range'

    Describe the bug

    using the editor-menu-bubble for adding a Link will result in the following error:

    Error in v-on handler: "IndexSizeError: Failed to execute 'setStart' on 'Range': The offset 4294967295 is larger than the node's length (16)."

    Steps to Reproduce / Codesandbox Example

    Browser: Chrome (Google Chrome, Vivaldi):

          <div
            class="menububble"
            :class="{ 'is-active': menu.isActive }"
            :style="`left: ${menu.left}px; bottom: ${menu.bottom}px;`"
          >
    
            <form class="menububble__form" v-if="linkMenuIsActive" @submit.prevent="setLinkUrl(commands.link, linkUrl)">
              <input class="menububble__input" type="text" v-model="linkUrl" placeholder="https://" ref="linkInput" @keydown.esc="hideLinkMenu"/>
              <button class="menububble__button" @click="setLinkUrl(commands.link, null)" type="button">
                <icon name="remove" />
              </button>
            </form>
    
            <template v-else>
              <button
                class="menububble__button"
                @click="showLinkMenu(getMarkAttrs('link'))"
                :class="{ 'is-active': isActive.link() }"
              >
                <span>{{ isActive.link() ? 'Update Link' : 'Add Link'}}</span>
                <icon name="link" />
              </button>
            </template>
    
          </div>
        </editor-menu-bubble>
    

    Screenshots

    Screen Shot 2021-01-25 at 12 56 36 bug help wanted 
    opened by itinance 29
  • TypeError: Cannot read property 'matchesNode' of null (TipTap for React)

    TypeError: Cannot read property 'matchesNode' of null (TipTap for React)

    Description

    Same issue as in https://github.com/ueberdosis/tiptap/issues/438. TypeError that crashes my app.

    Steps to reproduce the bug

    Happens on occasion when navigating to a page with a TipTap editor on it.

    CodeSandbox

    In the CSB below, run the tests, and observe the console spits out a bunch of these type errors for the browser. I don't know why it does this...

    https://codesandbox.io/s/tiptap-prose-matchesnode-error-yhvdc

    image

    Expected behavior

    No error.

    Environment?

    • operating system: OSX
    • browser: N/A
    • mobile/desktop: N/A
    • tiptap version: @tiptap/core@^2.0.0-beta.65

    Additional context

    I tried to keep the CSB example above as close to my current code as possible, minus other third-party libraries that would unnecessarily bloat the example.

    I am able to replicate the error consistently in my tests:

        Error: Uncaught [TypeError: Cannot read property 'matchesNode' of null]
            at reportException (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:62:24)
            at Timeout.task [as _onTimeout] (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/jsdom/lib/jsdom/browser/Window.js:521:9)
            at listOnTimeout (internal/timers.js:549:17)
            at processTimers (internal/timers.js:492:7) TypeError: Cannot read property 'matchesNode' of null
            at EditorView.updateStateInner (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/prosemirror-view/src/index.js:141:45)
            at EditorView.updateState (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/prosemirror-view/src/index.js:114:10)
            at Editor.dispatchTransaction (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/@tiptap/core/src/Editor.ts:299:15)
            at EditorView.dispatch (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/prosemirror-view/src/index.js:374:50)
            at Object.method [as focus] (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/@tiptap/core/src/CommandManager.ts:35:18)
            at /Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/@tiptap/core/src/Editor.ts:90:21
            at Timeout.task [as _onTimeout] (/Users/jasonhughes/sites/innovator-portal/innovator/client/node_modules/jsdom/lib/jsdom/browser/Window.js:516:19)
            at listOnTimeout (internal/timers.js:549:17)
            at processTimers (internal/timers.js:492:7)
    
    bug 
    opened by chasinhues 28
  • @tiptap/extension-collaboration is not compatible with ySyncPlugin  renderSnapshot

    @tiptap/extension-collaboration is not compatible with ySyncPlugin renderSnapshot

    What’s the bug you are facing?

    I am working on a project built on top of Tiptap and @tiptap/extension-collaboration. (Huge thank you for the libraries, they are amazing). I am trying to leverage YJS snapshots to build a feature that renders the document history (showing who edited what part of the doc) as described in the prosemirror demo by @dmonad.

    However, @tiptap/extension-collaboration does not allow me to configure the options object needed for ySyncPlugin so when it tries to read the permanentUserData prop it throws an error

    https://github.com/yjs/y-prosemirror/blob/7a3afbc0d8de35bc01bd63bfc9911318c115c4f7/src/plugins/sync-plugin.js#L447
    sync-plugin.js:446
    
    Uncaught TypeError: Cannot read properties of null (reading 'getUserByClientId')
        at computeYChange (sync-plugin.js:446:1)
        at YText.js:1028:1
        at transact (Transaction.js:398:1)
        at YXmlText.toDelta (YText.js:1008:1)
        at createTextNodesFromYText (sync-plugin.js:706:1)
        at createChildren (sync-plugin.js:638:1)
        at Array.forEach (<anonymous>)
        at createNodeFromYElement (sync-plugin.js:658:1)
        at sync-plugin.js:468:1
        at Array.map (<anonymous>)
    

    You can see here that the current extension only includes

    return [
          ySyncPlugin(fragment),
          yUndoPlugin(),
        ]
    

    vs

    return [
          ySyncPlugin(fragment, { permanentUserData, colors }),
          yUndoPlugin(),
        ]
    

    So I am unable to leverage renderSnapshot and unrenderSnapshot unless I fork the extension to be able to inject my own permanentUserData. I'm happy to send a PR but I wanted to understand if there was a reason behind this choice.

    Thanks!

    Which browser was this experienced in? Are any special extensions installed?

    Chrome, Firefox, Safari. Not a browser issue.

    How can we reproduce the bug on our side?

    const editor = useEditor({
      extensions: [
        // your extensions here ...
        Collaboration.configure({
          document: messagingProvider.doc,
        }),
        CollaborationCursor.configure({
          provider: messagingProvider,
        }),
       ....
      ]
    });
    const renderDocHistory = () => {
      const binding = ySyncPluginKey.getState(editor.view.state).binding;
      const doc = messagingProvider.doc;
      const prevSnapshot = Y.emptySnapshot;
      const snapshot = Y.snapshot(doc);
      binding.renderSnapshot(snapshot, prevSnapshot);
    };
    
    <div className="editor" role="document">
       <EditorContent className="editor__content" editor={editor} />
            <div className="editor__footer">
                 <button onClick={renderDocHistory}>Show History</button>
            </div>
    </div>
    

    fixed by updating https://github.com/ueberdosis/tiptap/tree/main/packages/extension-collaboration to

    export const Collaboration = Extension.create<CollaborationOptions>({
    
    ...
    
      addProseMirrorPlugins() {
        const fragment = this.options.fragment
          ? this.options.fragment
          : this.options.document.getXmlFragment(this.options.field)
      
        const permanentUserData = this.options.permanentUserData;
        const colors = this.options.colors;
        return [
          ySyncPlugin(fragment, { permanentUserData , colors  }),
          yUndoPlugin(),
        ]
      },
    })
    

    Can you provide a CodeSandbox?

    https://codesandbox.io/s/green-sea-1pbmj6?file=/src/App.js

    What did you expect to happen?

    I would expect @tiptap/extension-collaboration to be fully configurable with all the options allowed by ySyncPlugin in y-prosemirror

    const options = {
        colors,
        onFirstRender
        permanentUserData
    };
    Collaboration.configure({
        document,
        options
    }),
    

    Anything to add? (optional)

    No response

    Did you update your dependencies?

    • [X] Yes, I’ve updated my dependencies to use the latest version of all packages.

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    bug 
    opened by martarf 0
  • Accepting YouTube

    Accepting YouTube "shorts" urls

    What problem are you facing?

    Ensure that users can provide YouTube short urls as well.

    ie https://www.youtube.com/shorts/1H5UPEnzLkQ

    What’s the solution you would like to see?

    A slight change to the regex would solve the issue.

    What alternatives did you consider?

    Currently using a custom extension.

    Anything to add? (optional)

    Changing line 70 in the extension's utils adds shorts url support:

    const videoIdRegex = /(?:v=|shorts\/)([-\w]+)/gm
    

    I'd submit a pull request, but it's such a tiny change and the contributing doc said to submit ideas first.

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    feature request 
    opened by enkia 0
  • Virtual cursor when editor can't edit

    Virtual cursor when editor can't edit

    What problem are you facing?

    When the editor cannot be edited, I want to have a feedback of the click position on the editor when I click on it.

    What’s the solution you would like to see?

    Add a DecorationSet to the current selection.from position when the editor cannot be edited, using the plugin form.

    What alternatives did you consider?

    Or can add a pointer like CollaborationCursor to show the current selection position of the user's click when the editor cannot be edited, or show the editing cursor otherwise.

    Anything to add? (optional)

    Here is one way to achieve it.

    import { Extension } from '@tiptap/core'
    import { Plugin, PluginKey } from 'prosemirror-state'
    import { DecorationSet, Decoration } from 'prosemirror-view'
    
    const CustomCursorKey = 'custom-cursor'
    
    const createCursor = () => {
        const cursor = document.createElement('span')
        cursor.setAttribute(
            'style',
            `border-right: 1px solid #000; margin-right: -1px; position: relative; word-break: normal; pointer-events: none;`
        )
        return cursor
    }
    
    const CustomCursor = Extension.create({
        name: CustomCursorKey,
        addProseMirrorPlugins() {
            return [
                new Plugin({
                    key: new PluginKey(CustomCursorKey),
                    state: {
                        init(...params) {
                            const [, state] = params
                            return DecorationSet.create(state.doc, [])
                        },
                        apply: (...params) => {
                            const { isEditable } = this.editor
                            const [tr, , , newState] = params
                            let from = tr.curSelection.from
                            // cannot edit| selection is empty
                            if (!isEditable && newState.selection.empty) {
                                return DecorationSet.create(newState.doc, [
                                    Decoration.widget(from, () => createCursor(), { side: 100 })
                                ])
                            }
                            return null
                        }
                    },
                    props: {
                        decorations(state) {
                            return this.getState(state)
                        }
                    }
                })
            ]
        }
    })
    
    export { CustomCursor, CustomCursor as default }
    

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    feature request 
    opened by linkaiqiyi 0
  • Error: flushSync was called from inside a lifecycle method in <PureEditorContent>

    Error: flushSync was called from inside a lifecycle method in

    What’s the bug you are facing?

    The component import { EditorContent } from "@tiptap/react" is crashing for some reason.

    I'm getting the following error in console:

    Uncaught Error: flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.
        at flushSync (react-dom.development.js:21917:1)
        at PureEditorContent.maybeFlushSync (EditorContent.tsx:82:1)
        at PureEditorContent.removeRenderer (EditorContent.tsx:100:1)
        at ReactRenderer.destroy (ReactRenderer.tsx:93:1)
        at ReactNodeView.destroy (ReactNodeViewRenderer.tsx:173:1)
    ...
    

    More specifically here:

    The above error occurred in the <PureEditorContent> component:
        in PureEditorContent
        in PureEditorContent (at TipTap.js:154)
        in div (at TipTap.js:145)
    ...
    

    Reduced code:

    const TipTap = ({ editor, ...props }) => {
      return (
        <div className="tip-tap-editor-container text-editor">
          <EditorContent className="tip-tap-editor-content mt-5" editor={editor} />
        </div>
      )
    }
    

    If I remove the <EditorContent> the app doesn't crash.

    Not sure if this bug is only related to our implementation. Anyway, any help, clue or information is welcome in order to fix this issue which is urgent.

    Which browser was this experienced in? Are any special extensions installed?

    Google Chrome Version 108.0.5359.124 (Official Build) (arm64)

    macOs ventura 13.1

    How can we reproduce the bug on our side?

    Not sure.

    Can you provide a CodeSandbox?

    No response

    What did you expect to happen?

    Not crashing.

    Anything to add? (optional)

    Tip-tap package versions:

    {
        "@tiptap/extension-color": "^2.0.0-beta.209",
        "@tiptap/extension-highlight": "^2.0.0-beta.209",
        "@tiptap/extension-image": "^2.0.0-beta.209",
        "@tiptap/extension-link": "^2.0.0-beta.209",
        "@tiptap/extension-placeholder": "^2.0.0-beta.209",
        "@tiptap/extension-text-style": "^2.0.0-beta.209",
        "@tiptap/extension-underline": "^2.0.0-beta.209",
        "@tiptap/react": "^2.0.0-beta.209",
        "@tiptap/starter-kit": "^2.0.0-beta.209",
    }
    

    React version: 16.13.1 Node version: v14.19.1

    You can find the entire log here: tiptap.log


    Note: my app depends of this node version only

    Did you update your dependencies?

    • [X] Yes, I’ve updated my dependencies to use the latest version of all packages.

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    bug 
    opened by diegoulloao 3
  • Tiptap producing TypeScript errors during type-checking

    Tiptap producing TypeScript errors during type-checking

    What’s the bug you are facing?

    Hello! I'm using tiptap in my project. Recently I've tried to set up type-checking using tsc --noEmit --skipLibCheck and I've got this output in console:

    node_modules/@tiptap/core/src/commands/blur.ts:14:32 - error TS2339: Property 'blur' does not exist on type 'RawCommands'.
    
    export const blur: RawCommands['blur'] = () => ({ editor, view }) => {
    

    It's not the only error but they all looks the same.

    I think the issue is in module augmentation. We have the following interface exported from "@tiptap/core":

    export interface Commands<ReturnType = any> {
    }
    

    And it's augmented in every extension:

    declare module '@tiptap/core' {
      interface Commands<ReturnType> {
        blur: {
          /**
           * Removes focus from the editor.
           */
          blur: () => ReturnType,
        }
      }
    }
    

    But looks like that the interface is not augmented and resulting interface is still empty so other types are not inferred too.

    Снимок экрана 2022-12-28 в 20 25 52

    Which browser was this experienced in? Are any special extensions installed?

    This is not in the browser side

    How can we reproduce the bug on our side?

    I don't know

    Can you provide a CodeSandbox?

    No response

    What did you expect to happen?

    Tiptap should not be involved into type-checking in my project or it should not produce the errors

    Anything to add? (optional)

    No response

    Did you update your dependencies?

    • [X] Yes, I’ve updated my dependencies to use the latest version of all packages.

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    bug 
    opened by stryaponoff 3
  • Autopunctuation does not work on iOS Safari

    Autopunctuation does not work on iOS Safari

    What’s the bug you are facing?

    The autopunctuation feature that is part of iOS does not work with Tiptap using Safari.

    Here is a screen recording:

    https://user-images.githubusercontent.com/778111/209809833-c35908f8-30b5-49f5-8307-ebd79f5edbb1.MOV

    Which browser was this experienced in? Are any special extensions installed?

    Safari 15, no extensions

    How can we reproduce the bug on our side?

    1. Go to the default example https://tiptap.dev/examples/default
    2. Type in the word "The" then enter two spaces
    3. Notice that the two spaces are not replaced by a period and a space

    Can you provide a CodeSandbox?

    See https://tiptap.dev/examples/default.

    What did you expect to happen?

    I expected autopunctuation to work, ie two spaces is replaced with a period and a space. This functionality works with ProseMirror on iOS 15 Safari using the example at https://prosemirror.net/.

    Anything to add? (optional)

    No response

    Did you update your dependencies?

    • [X] Yes, I’ve updated my dependencies to use the latest version of all packages.

    Are you sponsoring us?

    • [ ] Yes, I’m a sponsor. 💖
    bug 
    opened by josephdpurcell 0
Releases(v2.0.0-beta.209)
  • v2.0.0-beta.209(Dec 16, 2022)

    Note: Version Bump to keep Tiptap Pro in Sync with Tiptap (v2.0.0-beta.209)

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.208...v2.0.0-beta.209

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.208(Dec 16, 2022)

    What's Changed

    • Fix: custom text serializers should override text serializers defined in the schema by @tovaschreier in https://github.com/ueberdosis/tiptap/pull/3546

    New Contributors

    • @tovaschreier made their first contribution in https://github.com/ueberdosis/tiptap/pull/3546

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.207...v2.0.0-beta.208

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.207(Dec 8, 2022)

    What's Changed

    • fix(extension-tables): add prosemirror-tables to peerDependencies

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.205...v2.0.0-beta.207

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.206(Dec 8, 2022)

    What's Changed

    • fix(extension-bubble-menu): don't debounce without valid selection by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3501
    • refactor(extension-youtube): rename utility function name by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3498
    • Check if url is valid before creating YouTube player by @umgustavo in https://github.com/ueberdosis/tiptap/pull/3484
    • Fix docs menus.md missing word by @kandros in https://github.com/ueberdosis/tiptap/pull/3457
    • build(deps): bump minimatch from 3.0.4 to 3.1.2 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3489

    New Contributors

    • @umgustavo made their first contribution in https://github.com/ueberdosis/tiptap/pull/3484
    • @kandros made their first contribution in https://github.com/ueberdosis/tiptap/pull/3457

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.205...v2.0.0-beta.206

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.205(Dec 8, 2022)

    What's Changed

    • fix(core): implement deleteCurrentNode command & fix node joining on Delete key by @bdbch in https://github.com/ueberdosis/tiptap/pull/3192
    • fix(link): allow to unset target attribute by @dargmuesli in https://github.com/ueberdosis/tiptap/pull/3425
    • feat(commands): add joinUp and joinDown command & refactor join command code by @bdbch in https://github.com/ueberdosis/tiptap/pull/3455
    • docs: rotate demo rooms by @patrickbaber in https://github.com/ueberdosis/tiptap/pull/3475
    • Draft: Moves all prosemirror deps to peerDependencies & devDependencies by @janthurau in https://github.com/ueberdosis/tiptap/pull/3487

    New Contributors

    • @dargmuesli made their first contribution in https://github.com/ueberdosis/tiptap/pull/3425
    • @janthurau made their first contribution in https://github.com/ueberdosis/tiptap/pull/3487

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.204...v2.0.0-beta.205

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.204(Nov 25, 2022)

    What's Changed

    • build(deps): bump loader-utils from 2.0.3 to 2.0.4 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3426
    • Fix cursor not following to new node when using a react node view by @ruipserra in https://github.com/ueberdosis/tiptap/pull/3331

    New Contributors

    • @ruipserra made their first contribution in https://github.com/ueberdosis/tiptap/pull/3331

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.203...v2.0.0-beta.204

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.203(Nov 24, 2022)

    What's Changed

    • fixes typo in suggestion.ts by @alejandrogarciasalas in https://github.com/ueberdosis/tiptap/pull/3386
    • docs(svelte): fix link to get started with svelte by @taismassaro in https://github.com/ueberdosis/tiptap/pull/3396
    • build(deps): bump loader-utils from 2.0.2 to 2.0.3 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3395
    • Update jobs.md by @montapro in https://github.com/ueberdosis/tiptap/pull/3432
    • extension/table: Fix prosemirror-tables dependency not using a correct namespace by @bdbch in https://github.com/ueberdosis/tiptap/pull/3448
    • typo: custom-extensions.md completely by @williamsk91 in https://github.com/ueberdosis/tiptap/pull/3447
    • Fix #3435 - CommonJS and ESM loading confusion by @tomi-bigpi in https://github.com/ueberdosis/tiptap/pull/3436

    New Contributors

    • @alejandrogarciasalas made their first contribution in https://github.com/ueberdosis/tiptap/pull/3386
    • @taismassaro made their first contribution in https://github.com/ueberdosis/tiptap/pull/3396
    • @williamsk91 made their first contribution in https://github.com/ueberdosis/tiptap/pull/3447
    • @tomi-bigpi made their first contribution in https://github.com/ueberdosis/tiptap/pull/3436

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.202...v2.0.0-beta.203

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.202(Nov 4, 2022)

    • BubbleMenu: rename delay option to updateDelay

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.201...v2.0.0-beta.202

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.201(Nov 4, 2022)

    What's Changed

    • build(deps): bump parse-url from 7.0.2 to 8.1.0 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3384
    • refactor(extension/bubble-menu): add debounce to bubble menu updates by @bdbch in https://github.com/ueberdosis/tiptap/pull/3385
    • build(deps): bump actions/setup-node from 3.4.1 to 3.5.1 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3318
    • docs: Fix typos in CHANGELOG.md by @rvrvrv in https://github.com/ueberdosis/tiptap/pull/3328
    • build(deps): bump actions/cache from 3.0.8 to 3.0.11 by @dependabot in https://github.com/ueberdosis/tiptap/pull/3317
    • fix: remove blur event listener from tippy element (#3365) by @MihirGH in https://github.com/ueberdosis/tiptap/pull/3366

    New Contributors

    • @rvrvrv made their first contribution in https://github.com/ueberdosis/tiptap/pull/3328
    • @MihirGH made their first contribution in https://github.com/ueberdosis/tiptap/pull/3366

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.200...v2.0.0-beta.201

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.200(Nov 4, 2022)

    What's Changed

    • build(deps): bump d3-color from 3.0.1 to 3.1.0 in /demos by @dependabot in https://github.com/ueberdosis/tiptap/pull/3260
    • docs: link YouTube node docs to proper GitHub url by @nielslanting in https://github.com/ueberdosis/tiptap/pull/3283
    • fix: typo in docs by @danielyuenhx in https://github.com/ueberdosis/tiptap/pull/3265
    • Fixed dragged text not being deleted after drop on another editor by @LuchoCateura in https://github.com/ueberdosis/tiptap/pull/3279
    • Fixed using both color and highlight together by @nkonev in https://github.com/ueberdosis/tiptap/pull/3311
    • Cleanup linkifyjs when the editor is destroyed by @educastellano in https://github.com/ueberdosis/tiptap/pull/3316
    • Feature/youtube parameters by @LuchoCateura in https://github.com/ueberdosis/tiptap/pull/3307
    • Fix installation and examples link by @catalinmiron in https://github.com/ueberdosis/tiptap/pull/3298
    • fix(docs): typo by @Calvein in https://github.com/ueberdosis/tiptap/pull/3362
    • fix(extension/placeholder): Resolve placeholder performance issues by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3361

    New Contributors

    • @nielslanting made their first contribution in https://github.com/ueberdosis/tiptap/pull/3283
    • @danielyuenhx made their first contribution in https://github.com/ueberdosis/tiptap/pull/3265
    • @LuchoCateura made their first contribution in https://github.com/ueberdosis/tiptap/pull/3279
    • @nkonev made their first contribution in https://github.com/ueberdosis/tiptap/pull/3311
    • @educastellano made their first contribution in https://github.com/ueberdosis/tiptap/pull/3316
    • @catalinmiron made their first contribution in https://github.com/ueberdosis/tiptap/pull/3298
    • @Calvein made their first contribution in https://github.com/ueberdosis/tiptap/pull/3362

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.199...v2.0.0-beta.200

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.199(Sep 30, 2022)

    What's Changed

    • fix(extension/link): fix last word value being undefined by @bdbch in https://github.com/ueberdosis/tiptap/pull/3258

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.198...v2.0.0-beta.199

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.198(Sep 29, 2022)

    What's Changed

    • Ensure text blocks exist before referencing them by @ScopeyNZ in https://github.com/ueberdosis/tiptap/pull/3251
    • fix(core): InputRules does not work for ranges containing multiple text nodes by @hamflx in https://github.com/ueberdosis/tiptap/pull/3205
    • fix(core) - support attributes being null/undefined by @albertogiunta in https://github.com/ueberdosis/tiptap/pull/3245
    • fix: set default allowedPrefixes null by @Matrixbirds in https://github.com/ueberdosis/tiptap/pull/3239

    New Contributors

    • @ScopeyNZ made their first contribution in https://github.com/ueberdosis/tiptap/pull/3251
    • @hamflx made their first contribution in https://github.com/ueberdosis/tiptap/pull/3205
    • @albertogiunta made their first contribution in https://github.com/ueberdosis/tiptap/pull/3245
    • @Matrixbirds made their first contribution in https://github.com/ueberdosis/tiptap/pull/3239

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.197...v2.0.0-beta.198

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.197(Sep 26, 2022)

    What's Changed

    • test: fix failing test by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3230
    • feat(extension-link): Change autolink to only apply after breaking a word by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3232
    • chore(maintainment): :rocket: update prosemirror packages by @bdbch in https://github.com/ueberdosis/tiptap/pull/3237
    • fix(core): can() does not work for marks by @C-Hess in https://github.com/ueberdosis/tiptap/pull/3223

    New Contributors

    • @C-Hess made their first contribution in https://github.com/ueberdosis/tiptap/pull/3232

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.196...v2.0.0-beta.197

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.196(Sep 20, 2022)

    What's Changed

    • feat(extension-typography): add servicemark input rule by @svenadlung in https://github.com/ueberdosis/tiptap/pull/3220
    • fix(types): fix link and table type errors by @johnfraney in https://github.com/ueberdosis/tiptap/pull/3208

    New Contributors

    • @johnfraney made their first contribution in https://github.com/ueberdosis/tiptap/pull/3208

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.195...v2.0.0-beta.196

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.195(Sep 14, 2022)

    What's Changed

    • fix: move React flushSync to microtask by @sampi in https://github.com/ueberdosis/tiptap/pull/3188
    • Fix bubble menu and floating menu being available when editor is not editable by @bdbch in https://github.com/ueberdosis/tiptap/pull/3195
    • feat: Add alias condition to code-block-lowlight by @dngwoodo in https://github.com/ueberdosis/tiptap/pull/3155

    New Contributors

    • @sampi made their first contribution in https://github.com/ueberdosis/tiptap/pull/3188
    • @dngwoodo made their first contribution in https://github.com/ueberdosis/tiptap/pull/3155

    Full Changelog: https://github.com/ueberdosis/tiptap/compare/v2.0.0-beta.194...v2.0.0-beta.195

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0-beta.194(Sep 11, 2022)

  • v2.0.0-beta.193(Sep 10, 2022)

  • [email protected](Aug 7, 2020)

  • [email protected](Jul 13, 2020)

  • [email protected](Jul 8, 2020)

    • Allow attributes for wrappers (#727)
    • fix XSS issue when importing through getHTML() (#747)
    • fix(markpasterule): parent is undefined for mark (#687)
    • update fuse.js to v6 and fix Suggestion mention search (#750)
    • Add option to put target for the created link (#619)
    • update to latest ProseMirror dependencies
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Apr 22, 2020)

    • isActive() works with multiple attributes now (fix #666)
    • change registerPlugin to add plugin after Extensions plugins (PR #658)
    • update dependencies
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Apr 11, 2020)

  • [email protected](Apr 2, 2020)

    • fix a bug where custom nodes gets destroyed on interaction (fix #652)
    • Remove menu event handlers on destroy (PR https://github.com/scrumpy/tiptap/pull/650)
    • check for allowed marks in pasteRule (fix #643)
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Apr 1, 2020)

    • Apply decorations in HighlightPlugin if change in named nodes (PR https://github.com/scrumpy/tiptap/pull/607)
    • set capture to true for mousedown event listener (PR https://github.com/scrumpy/tiptap/pull/646)
    • Allow extensions to define update behavior (PR https://github.com/scrumpy/tiptap/pull/603)
    • update ProseMirror dependencies
    Source code(tar.gz)
    Source code(zip)
  • [email protected](Dec 16, 2019)

  • [email protected](Dec 16, 2019)

  • [email protected](Dec 16, 2019)

  • [email protected](Dec 2, 2019)

  • [email protected](Dec 2, 2019)

  • [email protected](Dec 2, 2019)

    • added emptyEditorClass option for Placeholder (fix #463)
    • added support for historical paths (PR #511)
    • remove redundant escape character for regexp (PR #533)
    • update dependencies
    Source code(tar.gz)
    Source code(zip)
Owner
überdosis
A digital product company, building open-source software & working for clients.
überdosis
:tada: A magical vue admin https://panjiachen.github.io/vue-element-admin

English | 简体中文 | 日本語 | Spanish SPONSORED BY 活动服务销售平台 客户消息直达工作群 Introduction vue-element-admin is a production-ready front-end solution for admin inter

花裤衩 80.1k Dec 31, 2022
:eyes: Vue in React, React in Vue. Seamless integration of the two. :dancers:

vuera NOTE: This project is looking for a maintainer! Use Vue components in your React app: import React from 'react' import MyVueComponent from './My

Aleksandr Komarov 4k Dec 30, 2022
🎉 基于 vite 2.0 + vue 3.0 + vue-router 4.0 + vuex 4.0 + element-plus 的后台管理系统vue3-element-admin

vue3-element-admin ?? 基于 Vite 2.0 + Vue3.0 + Vue-Router 4.0 + Vuex 4.0 + element-plus 的后台管理系统 简介 vue3-element-admin 是一个后台前端解决方案,它基于 vue3 和 element-plu

雪月欧巴 84 Nov 28, 2022
Jenesius vue modal is simple library for Vue 3 only

Jenesius Vue Modal Jenesius vue modal is simple library for Vue 3 only . Site Documentation Installation npm i jenesius-vue-modal For add modals in yo

Архипцев Евгений 63 Dec 30, 2022
A template repository / quick start to build Azure Static Web Apps with a Node.js function. It uses Vue.js v3, Vue Router, Vuex, and Vite.js.

Azure Static Web App Template with Node.js API This is a template repository for creating Azure Static Web Apps that comes pre-configured with: Vue.js

Marc Duiker 6 Jun 25, 2022
Mosha-vue-toastify - A light weight and fun Vue 3 toast or notification or snack bar or however you wanna call it library.

Mosha Vue Toastify A lightweight and fun Vue 3 toast or notification or snack bar or however you wanna call it library. English | 简体中文 Talk is cheap,

Baidi Liu 187 Jan 2, 2023
A plugin that can help you create project friendly with Vue for @vue/cli 4.5

vue-cli-plugin-patch A plugin that can help you create project friendly with Vue for @vue/cli 4.5. Install First you need to install @vue/cli globally

null 2 Jan 6, 2022
Veloce: Starter template that uses Vue 3, Vite, TypeScript, SSR, Pinia, Vue Router, Express and Docker

Veloce Lightning-fast cold server start Instant hot module replacement (HMR) and dev SSR True on-demand compilation Tech Stack Vue 3: UI Rendering lib

Alan Morel 10 Oct 7, 2022
📓 The UI component explorer. Develop, document, & test React, Vue, Angular, Web Components, Ember, Svelte & more!

Build bulletproof UI components faster Storybook is a development environment for UI components. It allows you to browse a component library, view the

Storybook 75.9k Jan 9, 2023
A Vue.js 2.0 UI Toolkit for Web

A Vue.js 2.0 UI Toolkit for Web. Element will stay with Vue 2.x For Vue 3.0, we recommend using Element Plus from the same team Links Homepage and doc

饿了么前端 53k Jan 3, 2023
The Intuitive Vue Framework

Build your next Vue.js application with confidence using Nuxt: a framework making web development simple and powerful. Links ?? Documentation: https:/

Nuxt 41.8k Jan 5, 2023
🐉 Material Component Framework for Vue

Supporting Vuetify Vuetify is a MIT licensed project that is developed and maintained full-time by John Leider and Heather Leider; with support from t

vuetify 36.2k Jan 3, 2023
🛠️ Standard Tooling for Vue.js Development

Vue CLI Vue CLI is the Standard Tooling for Vue.js Development. Documentation Docs are available at https://cli.vuejs.org/ - we are still working on r

vuejs 29.6k Jan 4, 2023
🗃️ Centralized State Management for Vue.js.

Vuex ?? HEADS UP! You're currently looking at Vuex 3 branch. If you're looking for Vuex 4, please check out 4.0 branch. Vuex is a state management pat

vuejs 27.9k Dec 30, 2022
A high quality UI Toolkit built on Vue.js 2.0

iView A high quality UI Toolkit built on Vue.js. Docs 3.x | 2.x | 1.x Features Dozens of useful and beautiful components. Friendly API. It's made for

iView 24k Jan 5, 2023
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

vue-next This is the repository for Vue 3.0. Quickstart Via CDN: <script src="https://unpkg.com/vue@next"></script> In-browser playground on Codepen S

vuejs 34.6k Jan 9, 2023
NativeScript empowers you to access native api's from JavaScript directly. Angular, Vue, Svelte, React and you name it compatible.

NativeScript empowers you to access native APIs from JavaScript directly. The framework currently provides iOS and Android runtimes for rich mobile de

NativeScript 22k Jan 4, 2023
📝 Minimalistic Vue-powered static site generator

VuePress 2 is coming! Please check out vuepress-next. Documentation Check out our docs at https://vuepress.vuejs.org/. Showcase Awesome VuePress vuepr

vuejs 21.1k Jan 4, 2023
🚦 The official router for Vue.js.

vue-router This is vue-router 3.0 which works only with Vue 2.0. For the 1.x router see the 1.0 branch. Supporting Vue Router Vue Router is part of th

vuejs 18.9k Jan 3, 2023