mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-01-18 06:03:22 +08:00
experimental annotations
commit 41c0fe487b78fdabac4fc0abd922fc6b23b87821 Author: Hans Pagel <hans.pagel@ueber.io> Date: Tue Jan 19 14:55:36 2021 +0100 move to the new experiments structure commit 5b22dcaf042e247b138fc00ccaea1f1baa52b7a4 Author: Hans Pagel <hans.pagel@ueber.io> Date: Tue Jan 19 14:50:21 2021 +0100 enable typescript checks again commit 50d566f72c1eda9175075173e9b11c125fb0d767 Merge: 5352c488 a7d52bb0 Author: Hans Pagel <hans.pagel@ueber.io> Date: Tue Jan 19 14:49:47 2021 +0100 Merge branch 'feature/annotations' of github.com:ueberdosis/tiptap-next into feature/annotations commit 5352c4889f7d443148f6507bd0c372eec0b0a1dc Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 22:44:52 2021 +0100 more fiddling with Y.js commit e7c7fb70e7724ac3134de0aa47db06bc72a7925a Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 21:42:51 2021 +0100 fiddle around with Y.js commit a8b8268d6f3025a407caefed22c9db5657ca04f5 Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 20:18:21 2021 +0100 refactoring commit 6bbc94ff417323bedac6c9cbcb541cbfdb471090 Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 20:15:57 2021 +0100 refactoring commit dbdb3d3039bb818a973bb07c1c05c14ec73f6110 Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 14:59:56 2021 +0100 refactoring commit 1d8038dd6b27f00d723b547d4ebb75351608b2d4 Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 11:07:17 2021 +0100 clean up commit 4024ceaa7afddf890dd89610f487bd58231f1e09 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 22:01:09 2021 +0100 refactoring commit 4659583eee59571716cadaa821200f9cded5e2a0 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:49:08 2021 +0100 disable typescript errors for now commit 4a30fd13e4f91dd740fecd98e45972712ad9b742 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:48:23 2021 +0100 code style commit 1209ebafb21ab94f287d3c81db72dcb0d66d02d6 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:45:20 2021 +0100 add a comment, set default class commit 3a4394e4f107ad6df58d66eb690e25a4e58f9176 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:41:03 2021 +0100 strange refactoring (wip) commit 32e2d8a29bde0e282092799c69b1f32a85eb1251 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 17:19:12 2021 +0100 add extension documentation page, refactoring commit 4f9460895fce2c91399d230aa28d34d22bd11f8f Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 15:23:16 2021 +0100 refactoring commit 59d23958d524eb6055772880a525ec6828b93e35 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:54:25 2021 +0100 refactoring commit 66ea1cd22634af1d00b19e95274ffa60bcbd5506 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:52:49 2021 +0100 clean up commit 0d6a624029ef2318c5567db0de776343beefeb27 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:33:54 2021 +0100 refactoring commit 887767f78da94cd15387b581cf6b5c0f565f4b12 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:12:58 2021 +0100 refactoring commit c15bda12bdc76d7f901ed27740d85467b07e372b Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:23:57 2021 +0100 refactoring commit 97e7d1b527cde1382ee74e6b8494aca140b66f02 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:18:14 2021 +0100 clean up commit 2b28e35902209b95fa6beb12c7e64cb9efbb47ad Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:15:18 2021 +0100 refactoring commit 8612666b567ef8d4d8497d3b4dc063ecab7d85ed Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:11:15 2021 +0100 remove version commit f3169a29ea78a0b566a49c7885e687d9ecc09787 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:09:41 2021 +0100 code style commit 4d1c13ef4c00ddb49ad645983a092e7b4dbff60d Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:07:05 2021 +0100 refactoring commit 393e05278ab26b1d516404949ac6b6557e138085 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 21:47:16 2021 +0100 refactoring commit 65ee8f272578bbc172a5a82f634cc483d1314e58 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 21:32:24 2021 +0100 add crappy styling commit 816f031d5903ae2cb12f8e216f9f459e1716ec12 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 21:24:29 2021 +0100 add basic annotation plugin commit fa5ef2334a05a3ff06242f2e4f9288fe8aa405ce Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 16:19:15 2021 +0100 init new package commit a7d52bb0d4e2f7979ef87a341da0d15b68213f6a Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 22:44:52 2021 +0100 more fiddling with Y.js commit 2ad9d5047e27bb6fe1dbe398f4b3ccface028d6b Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 21:42:51 2021 +0100 fiddle around with Y.js commit 315dc512af2c26dd4f9d2c55b3b629530c60da8e Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 20:18:21 2021 +0100 refactoring commit 058e79f7efc2385910846a93a6af7e4f40f0d976 Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 20:15:57 2021 +0100 refactoring commit 576e645797a923aee43e059e7b3485bf924683a4 Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 14:59:56 2021 +0100 refactoring commit 46798f194fdbb6b5781818e6386efc5c089b46cc Author: Hans Pagel <hans.pagel@ueber.io> Date: Fri Jan 15 11:07:17 2021 +0100 clean up commit ed7ebd39e13a1ed63931d19a08c2cc7a030f0e0a Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 22:01:09 2021 +0100 refactoring commit 3d61a206c8f70601845da191e92693baf4cc7f28 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:49:08 2021 +0100 disable typescript errors for now commit cc2286d82ade7356fa998bfcd2dea2eafaa2f122 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:48:23 2021 +0100 code style commit bb9fb292693f929793663b83853083157c384136 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:45:20 2021 +0100 add a comment, set default class commit d547e74f092de6457a574b3d6b852bde3b408c8d Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 21:41:03 2021 +0100 strange refactoring (wip) commit 99e415b4eba9e4fa704cbe77f053860bd7ae8b1b Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 17:19:12 2021 +0100 add extension documentation page, refactoring commit ba585e6abe1b56c8c1fcd4e68057d967c23ad67e Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 15:23:16 2021 +0100 refactoring commit 2981591b8b568e2b41f4f81930d67f75b0ffcd6d Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:54:25 2021 +0100 refactoring commit 4083f3e3ac3f0d8ff54bae78ebb3e957f2f20309 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:52:49 2021 +0100 clean up commit 409a060be38d50fda542f988780481cffc94c54e Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:33:54 2021 +0100 refactoring commit fb1d0dc46af4a067165dcca19c9b1ba8c7a5cfc9 Author: Hans Pagel <hans.pagel@ueber.io> Date: Thu Jan 14 12:12:58 2021 +0100 refactoring commit 6cba6e0d098c0f3d3d4ec1f0e74ab50aa7966d31 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:23:57 2021 +0100 refactoring commit 9f8b6ef0f5455e5c8b331258d9168d01c67e29b6 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:18:14 2021 +0100 clean up commit 514c4d08039352d9c96212116fc59cb676f86e0b Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:15:18 2021 +0100 refactoring commit 3b0b99d0029130696b7651a9a417bcbee5a35b6d Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:11:15 2021 +0100 remove version commit 64fc138d73d9981b8e187c703c68146be6276664 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:09:41 2021 +0100 code style commit cb42c8c504bc02c929bd041a1f1b87c3a8f068f8 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 22:07:05 2021 +0100 refactoring commit 4203615a35d34cd6988ac0377507f32f197860af Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 21:47:16 2021 +0100 refactoring commit cf476d899193540013da22c4d078c1daca86f2d3 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 21:32:24 2021 +0100 add crappy styling commit 59a7639ee9c9fb7f3f57c376220a20baec93bba2 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 21:24:29 2021 +0100 add basic annotation plugin commit 8d2d9158cc1611da18432d76925c002731d51d09 Author: Hans Pagel <hans.pagel@ueber.io> Date: Wed Jan 13 16:19:15 2021 +0100 init new package
This commit is contained in:
parent
5452095343
commit
7f63a0b2e0
@ -0,0 +1,10 @@
|
||||
export class AnnotationItem {
|
||||
public id!: number
|
||||
|
||||
public text!: string
|
||||
|
||||
constructor(id: number, text: string) {
|
||||
this.id = id
|
||||
this.text = text
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Plugin, PluginKey } from 'prosemirror-state'
|
||||
import { AnnotationState } from './AnnotationState'
|
||||
|
||||
export const AnnotationPluginKey = new PluginKey('annotation')
|
||||
|
||||
export const AnnotationPlugin = (options: any) => new Plugin({
|
||||
key: AnnotationPluginKey,
|
||||
state: {
|
||||
init: AnnotationState.init,
|
||||
apply(transaction, prevState) {
|
||||
return prevState.apply(transaction)
|
||||
},
|
||||
},
|
||||
props: {
|
||||
decorations(state) {
|
||||
const { decorations } = this.getState(state)
|
||||
const { selection } = state
|
||||
|
||||
if (!selection.empty) {
|
||||
return decorations
|
||||
}
|
||||
|
||||
const annotations = this
|
||||
.getState(state)
|
||||
.annotationsAt(selection.from)
|
||||
|
||||
options.onUpdate(annotations)
|
||||
|
||||
return decorations
|
||||
},
|
||||
|
||||
},
|
||||
})
|
@ -0,0 +1,95 @@
|
||||
import { Decoration, DecorationSet } from 'prosemirror-view'
|
||||
import { ySyncPluginKey } from 'y-prosemirror'
|
||||
import { AnnotationPluginKey } from './AnnotationPlugin'
|
||||
|
||||
export class AnnotationState {
|
||||
private decorations: any
|
||||
|
||||
constructor(decorations: any) {
|
||||
this.decorations = decorations
|
||||
}
|
||||
|
||||
findAnnotation(id: number) {
|
||||
const current = this.decorations.find()
|
||||
|
||||
for (let i = 0; i < current.length; i += 1) {
|
||||
if (current[i].spec.data.id === id) {
|
||||
return current[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
annotationsAt(position: number) {
|
||||
return this.decorations.find(position, position)
|
||||
}
|
||||
|
||||
apply(transaction: any) {
|
||||
console.log('transaction', transaction.meta, transaction.docChanged, transaction)
|
||||
|
||||
const yjsTransaction = transaction.getMeta(ySyncPluginKey)
|
||||
if (yjsTransaction) {
|
||||
// TODO: Map positions
|
||||
// absolutePositionToRelativePosition(state.selection.anchor, pmbinding.type, pmbinding.mapping)
|
||||
console.log('map positions', transaction, yjsTransaction)
|
||||
|
||||
return this
|
||||
|
||||
// const { binding } = yjsTransaction
|
||||
// console.log({ binding }, { transaction }, transaction.docChanged)
|
||||
// console.log('yjsTransaction.isChangeOrigin', yjsTransaction.isChangeOrigin)
|
||||
|
||||
// console.log('yjs mapping', yjsTransaction.binding?.mapping)
|
||||
// console.log('all decorations', this.decorations.find())
|
||||
// console.log('original prosemirror mapping', this.decorations.map(transaction.mapping, transaction.doc))
|
||||
// console.log('difference between ProseMirror & Y.js', transaction.mapping, yjsTransaction.binding?.mapping)
|
||||
|
||||
// Code to sync the selection:
|
||||
// export const getRelativeSelection = (pmbinding, state) => ({
|
||||
// anchor: absolutePositionToRelativePosition(state.selection.anchor, pmbinding.type, pmbinding.mapping),
|
||||
// head: absolutePositionToRelativePosition(state.selection.head, pmbinding.type, pmbinding.mapping)
|
||||
// })
|
||||
|
||||
// console.log(yjsTransaction.binding.mapping, transaction.curSelection.anchor)
|
||||
}
|
||||
|
||||
if (transaction.docChanged) {
|
||||
// TODO: Fixes the initial load (complete replace of the document)
|
||||
// return this
|
||||
|
||||
// TODO: Fixes later changes (typing before the annotation)
|
||||
const decorations = this.decorations.map(transaction.mapping, transaction.doc)
|
||||
|
||||
return new AnnotationState(decorations)
|
||||
}
|
||||
|
||||
const action = transaction.getMeta(AnnotationPluginKey)
|
||||
const actionType = action && action.type
|
||||
|
||||
if (action) {
|
||||
let { decorations } = this
|
||||
|
||||
if (actionType === 'addAnnotation') {
|
||||
decorations = decorations.add(transaction.doc, [
|
||||
Decoration.inline(action.from, action.to, { class: 'annotation' }, { data: action.data }),
|
||||
])
|
||||
} else if (actionType === 'deleteAnnotation') {
|
||||
decorations = decorations.remove([
|
||||
this.findAnnotation(action.id),
|
||||
])
|
||||
}
|
||||
|
||||
return new AnnotationState(decorations)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
static init(config: any, state: any) {
|
||||
// TODO: Load initial decorations from Y.js?
|
||||
const decorations = DecorationSet.create(state.doc, [
|
||||
Decoration.inline(105, 190, { class: 'annotation' }, { data: { id: 123, content: 'foobar' } }),
|
||||
])
|
||||
|
||||
return new AnnotationState(decorations)
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
import { Extension, Command } from '@tiptap/core'
|
||||
import { AnnotationItem } from './AnnotationItem'
|
||||
import { AnnotationPlugin, AnnotationPluginKey } from './AnnotationPlugin'
|
||||
|
||||
function randomId() {
|
||||
return Math.floor(Math.random() * 0xffffffff)
|
||||
}
|
||||
|
||||
export interface AnnotationOptions {
|
||||
HTMLAttributes: {
|
||||
[key: string]: any
|
||||
},
|
||||
onUpdate: (items: [any?]) => {},
|
||||
}
|
||||
|
||||
export const Annotation = Extension.create({
|
||||
name: 'annotation',
|
||||
|
||||
defaultOptions: <AnnotationOptions>{
|
||||
HTMLAttributes: {
|
||||
class: 'annotation',
|
||||
},
|
||||
onUpdate: decorations => decorations,
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
addAnnotation: (content: any): Command => ({ dispatch, state }) => {
|
||||
const { selection } = state
|
||||
|
||||
if (selection.empty) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (dispatch && content) {
|
||||
dispatch(state.tr.setMeta(AnnotationPluginKey, {
|
||||
type: 'addAnnotation',
|
||||
from: selection.from,
|
||||
to: selection.to,
|
||||
data: new AnnotationItem(
|
||||
randomId(),
|
||||
content,
|
||||
),
|
||||
}))
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
deleteAnnotation: (id: number): Command => ({ dispatch, state }) => {
|
||||
if (dispatch) {
|
||||
dispatch(state.tr.setMeta(AnnotationPluginKey, { type: 'deleteAnnotation', id }))
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
addProseMirrorPlugins() {
|
||||
return [
|
||||
AnnotationPlugin(this.options),
|
||||
]
|
||||
},
|
||||
})
|
||||
|
||||
declare module '@tiptap/core' {
|
||||
interface AllExtensions {
|
||||
Annotation: typeof Annotation,
|
||||
}
|
||||
}
|
5
docs/src/demos/Experiments/Annotation/extension/index.ts
Normal file
5
docs/src/demos/Experiments/Annotation/extension/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { Annotation } from './annotation'
|
||||
|
||||
export * from './annotation'
|
||||
|
||||
export default Annotation
|
7
docs/src/demos/Experiments/Annotation/index.spec.js
Normal file
7
docs/src/demos/Experiments/Annotation/index.spec.js
Normal file
@ -0,0 +1,7 @@
|
||||
context('/api/extensions/annotations', () => {
|
||||
before(() => {
|
||||
cy.visit('/api/extensions/annotations')
|
||||
})
|
||||
|
||||
// TODO: Write tests
|
||||
})
|
87
docs/src/demos/Experiments/Annotation/index.vue
Normal file
87
docs/src/demos/Experiments/Annotation/index.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="editor">
|
||||
<button @click="addAnnotation" :disabled="!editor.can().addAnnotation()">
|
||||
add annotation
|
||||
</button>
|
||||
<editor-content :editor="editor" />
|
||||
<div v-for="comment in comments" :key="comment.type.spec.data.id">
|
||||
{{ comment.type.spec.data }}
|
||||
|
||||
<button @click="deleteAnnotation(comment.type.spec.data.id)">
|
||||
remove
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor, EditorContent } from '@tiptap/vue-starter-kit'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import Annotation from './extension'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
comments: [],
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
Annotation.configure({
|
||||
onUpdate: items => { this.comments = items },
|
||||
}),
|
||||
],
|
||||
content: `
|
||||
<p>
|
||||
Annotations can be used to add additional information to the content, for example comments. They live on a different level than the actual editor content.
|
||||
</p>
|
||||
<p>
|
||||
This example allows you to add plain text, but you’re free to add more complex data, for example JSON from another tiptap instance. :-)
|
||||
</p>
|
||||
`,
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
addAnnotation() {
|
||||
const content = prompt('Annotation', '')
|
||||
|
||||
this.editor.commands.addAnnotation(content)
|
||||
},
|
||||
deleteAnnotation(id) {
|
||||
this.editor.commands.deleteAnnotation(id)
|
||||
},
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* Basic editor styles */
|
||||
.ProseMirror {
|
||||
> * + * {
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.annotation {
|
||||
background: #9DEF8F;
|
||||
}
|
||||
</style>
|
7
docs/src/demos/Experiments/Comments/index.spec.js
Normal file
7
docs/src/demos/Experiments/Comments/index.spec.js
Normal file
@ -0,0 +1,7 @@
|
||||
context('/examples/annotations', () => {
|
||||
before(() => {
|
||||
cy.visit('/examples/annotations')
|
||||
})
|
||||
|
||||
// TODO: Write tests
|
||||
})
|
145
docs/src/demos/Experiments/Comments/index.vue
Normal file
145
docs/src/demos/Experiments/Comments/index.vue
Normal file
@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="editor">
|
||||
<h2>
|
||||
Original
|
||||
</h2>
|
||||
<button @click="addComment" :disabled="!editor.can().addAnnotation()">
|
||||
comment
|
||||
</button>
|
||||
<editor-content :editor="editor" />
|
||||
<div v-for="comment in comments" :key="comment.type.spec.data.id">
|
||||
{{ comment.type.spec.data }}
|
||||
|
||||
<button @click="deleteComment(comment.type.spec.data.id)">
|
||||
remove
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- <br>
|
||||
<h2>
|
||||
ProseMirror JSON from Y.js document
|
||||
</h2>
|
||||
{{ rawDocument }} -->
|
||||
|
||||
<br>
|
||||
<h2>
|
||||
Y.js document
|
||||
</h2>
|
||||
{{ json }}
|
||||
|
||||
<br>
|
||||
<h2>
|
||||
Mirror
|
||||
</h2>
|
||||
<editor-content :editor="anotherEditor" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor, EditorContent } from '@tiptap/vue-starter-kit'
|
||||
import Document from '@tiptap/extension-document'
|
||||
import Paragraph from '@tiptap/extension-paragraph'
|
||||
import Text from '@tiptap/extension-text'
|
||||
import Collaboration from '@tiptap/extension-collaboration'
|
||||
import Bold from '@tiptap/extension-bold'
|
||||
import Heading from '@tiptap/extension-heading'
|
||||
import * as Y from 'yjs'
|
||||
import { yDocToProsemirrorJSON } from 'y-prosemirror'
|
||||
import Annotation from '../Annotation/extension'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EditorContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
anotherEditor: null,
|
||||
comments: [],
|
||||
ydoc: null,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.ydoc = new Y.Doc()
|
||||
|
||||
this.editor = new Editor({
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
Bold,
|
||||
Heading,
|
||||
Annotation.configure({
|
||||
onUpdate: items => { this.comments = items },
|
||||
}),
|
||||
Collaboration.configure({
|
||||
document: this.ydoc,
|
||||
}),
|
||||
],
|
||||
content: `
|
||||
<p>
|
||||
Annotations can be used to add additional information to the content, for example comments. They live on a different level than the actual editor content.
|
||||
</p>
|
||||
<p>
|
||||
This example allows you to add plain text, but you’re free to add more complex data, for example JSON from another tiptap instance. :-)
|
||||
</p>
|
||||
`,
|
||||
})
|
||||
|
||||
this.anotherEditor = new Editor({
|
||||
extensions: [
|
||||
Document,
|
||||
Paragraph,
|
||||
Text,
|
||||
// Annotation.configure({
|
||||
// onUpdate: items => { this.comments = items },
|
||||
// }),
|
||||
Collaboration.configure({
|
||||
document: this.ydoc,
|
||||
}),
|
||||
],
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
addComment() {
|
||||
const content = prompt('Comment', '')
|
||||
|
||||
this.editor.commands.addAnnotation(content)
|
||||
},
|
||||
deleteComment(id) {
|
||||
this.editor.commands.deleteAnnotation(id)
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
rawDocument() {
|
||||
return yDocToProsemirrorJSON(this.ydoc, 'default')
|
||||
},
|
||||
json() {
|
||||
return this.ydoc.toJSON()
|
||||
},
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
this.editor.destroy()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* Basic editor styles */
|
||||
.ProseMirror {
|
||||
> * + * {
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
}
|
||||
|
||||
.annotation {
|
||||
background: #9DEF8F;
|
||||
}
|
||||
</style>
|
8
docs/src/docPages/api/extensions/annotation.md
Normal file
8
docs/src/docPages/api/extensions/annotation.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Annotation
|
||||
TODO
|
||||
|
||||
## Source code
|
||||
[packages/extension-annotation/](https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-annotation/)
|
||||
|
||||
## Usage
|
||||
<demo name="Extensions/Annotation" highlight="24,44-46,60-67" />
|
@ -2,3 +2,5 @@
|
||||
Congratulations! You’ve found our secret playground with a list of experiments. Be aware, that nothing here is ready to use. Feel free to play around, but please, don’t open an issue for a bug you’ve found here or send pull requests. :-)
|
||||
|
||||
* [Linter](/experiments/linter)
|
||||
* [Annotation](/experiments/annotation)
|
||||
* [Comments](/experiments/comments)
|
||||
|
5
docs/src/docPages/experiments/annotation.md
Normal file
5
docs/src/docPages/experiments/annotation.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Annotation
|
||||
|
||||
⚠️ Experiment
|
||||
|
||||
<demo name="Experiments/Annotation" />
|
5
docs/src/docPages/experiments/comments.md
Normal file
5
docs/src/docPages/experiments/comments.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Comments
|
||||
|
||||
⚠️ Experiment
|
||||
|
||||
<demo name="Experiments/Comments" />
|
@ -35,6 +35,10 @@
|
||||
link: /examples/drawing
|
||||
- title: Multiple editors
|
||||
link: /examples/multiple-editors
|
||||
- title: Comments
|
||||
link: /examples/comments
|
||||
draft: true
|
||||
|
||||
|
||||
- title: Guide
|
||||
items:
|
||||
@ -151,6 +155,9 @@
|
||||
- title: Extensions
|
||||
link: /api/extensions
|
||||
items:
|
||||
- title: Annotation
|
||||
link: /api/extensions/annotation
|
||||
draft: true
|
||||
- title: Collaboration
|
||||
link: /api/extensions/collaboration
|
||||
type: pro
|
||||
|
Loading…
Reference in New Issue
Block a user