From 7f63a0b2e0b22ddcc629b012bc8d287c8b8d665a Mon Sep 17 00:00:00 2001 From: Hans Pagel Date: Tue, 19 Jan 2021 14:57:41 +0100 Subject: [PATCH] experimental annotations commit 41c0fe487b78fdabac4fc0abd922fc6b23b87821 Author: Hans Pagel Date: Tue Jan 19 14:55:36 2021 +0100 move to the new experiments structure commit 5b22dcaf042e247b138fc00ccaea1f1baa52b7a4 Author: Hans Pagel Date: Tue Jan 19 14:50:21 2021 +0100 enable typescript checks again commit 50d566f72c1eda9175075173e9b11c125fb0d767 Merge: 5352c488 a7d52bb0 Author: Hans Pagel 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 Date: Fri Jan 15 22:44:52 2021 +0100 more fiddling with Y.js commit e7c7fb70e7724ac3134de0aa47db06bc72a7925a Author: Hans Pagel Date: Fri Jan 15 21:42:51 2021 +0100 fiddle around with Y.js commit a8b8268d6f3025a407caefed22c9db5657ca04f5 Author: Hans Pagel Date: Fri Jan 15 20:18:21 2021 +0100 refactoring commit 6bbc94ff417323bedac6c9cbcb541cbfdb471090 Author: Hans Pagel Date: Fri Jan 15 20:15:57 2021 +0100 refactoring commit dbdb3d3039bb818a973bb07c1c05c14ec73f6110 Author: Hans Pagel Date: Fri Jan 15 14:59:56 2021 +0100 refactoring commit 1d8038dd6b27f00d723b547d4ebb75351608b2d4 Author: Hans Pagel Date: Fri Jan 15 11:07:17 2021 +0100 clean up commit 4024ceaa7afddf890dd89610f487bd58231f1e09 Author: Hans Pagel Date: Thu Jan 14 22:01:09 2021 +0100 refactoring commit 4659583eee59571716cadaa821200f9cded5e2a0 Author: Hans Pagel Date: Thu Jan 14 21:49:08 2021 +0100 disable typescript errors for now commit 4a30fd13e4f91dd740fecd98e45972712ad9b742 Author: Hans Pagel Date: Thu Jan 14 21:48:23 2021 +0100 code style commit 1209ebafb21ab94f287d3c81db72dcb0d66d02d6 Author: Hans Pagel Date: Thu Jan 14 21:45:20 2021 +0100 add a comment, set default class commit 3a4394e4f107ad6df58d66eb690e25a4e58f9176 Author: Hans Pagel Date: Thu Jan 14 21:41:03 2021 +0100 strange refactoring (wip) commit 32e2d8a29bde0e282092799c69b1f32a85eb1251 Author: Hans Pagel Date: Thu Jan 14 17:19:12 2021 +0100 add extension documentation page, refactoring commit 4f9460895fce2c91399d230aa28d34d22bd11f8f Author: Hans Pagel Date: Thu Jan 14 15:23:16 2021 +0100 refactoring commit 59d23958d524eb6055772880a525ec6828b93e35 Author: Hans Pagel Date: Thu Jan 14 12:54:25 2021 +0100 refactoring commit 66ea1cd22634af1d00b19e95274ffa60bcbd5506 Author: Hans Pagel Date: Thu Jan 14 12:52:49 2021 +0100 clean up commit 0d6a624029ef2318c5567db0de776343beefeb27 Author: Hans Pagel Date: Thu Jan 14 12:33:54 2021 +0100 refactoring commit 887767f78da94cd15387b581cf6b5c0f565f4b12 Author: Hans Pagel Date: Thu Jan 14 12:12:58 2021 +0100 refactoring commit c15bda12bdc76d7f901ed27740d85467b07e372b Author: Hans Pagel Date: Wed Jan 13 22:23:57 2021 +0100 refactoring commit 97e7d1b527cde1382ee74e6b8494aca140b66f02 Author: Hans Pagel Date: Wed Jan 13 22:18:14 2021 +0100 clean up commit 2b28e35902209b95fa6beb12c7e64cb9efbb47ad Author: Hans Pagel Date: Wed Jan 13 22:15:18 2021 +0100 refactoring commit 8612666b567ef8d4d8497d3b4dc063ecab7d85ed Author: Hans Pagel Date: Wed Jan 13 22:11:15 2021 +0100 remove version commit f3169a29ea78a0b566a49c7885e687d9ecc09787 Author: Hans Pagel Date: Wed Jan 13 22:09:41 2021 +0100 code style commit 4d1c13ef4c00ddb49ad645983a092e7b4dbff60d Author: Hans Pagel Date: Wed Jan 13 22:07:05 2021 +0100 refactoring commit 393e05278ab26b1d516404949ac6b6557e138085 Author: Hans Pagel Date: Wed Jan 13 21:47:16 2021 +0100 refactoring commit 65ee8f272578bbc172a5a82f634cc483d1314e58 Author: Hans Pagel Date: Wed Jan 13 21:32:24 2021 +0100 add crappy styling commit 816f031d5903ae2cb12f8e216f9f459e1716ec12 Author: Hans Pagel Date: Wed Jan 13 21:24:29 2021 +0100 add basic annotation plugin commit fa5ef2334a05a3ff06242f2e4f9288fe8aa405ce Author: Hans Pagel Date: Wed Jan 13 16:19:15 2021 +0100 init new package commit a7d52bb0d4e2f7979ef87a341da0d15b68213f6a Author: Hans Pagel Date: Fri Jan 15 22:44:52 2021 +0100 more fiddling with Y.js commit 2ad9d5047e27bb6fe1dbe398f4b3ccface028d6b Author: Hans Pagel Date: Fri Jan 15 21:42:51 2021 +0100 fiddle around with Y.js commit 315dc512af2c26dd4f9d2c55b3b629530c60da8e Author: Hans Pagel Date: Fri Jan 15 20:18:21 2021 +0100 refactoring commit 058e79f7efc2385910846a93a6af7e4f40f0d976 Author: Hans Pagel Date: Fri Jan 15 20:15:57 2021 +0100 refactoring commit 576e645797a923aee43e059e7b3485bf924683a4 Author: Hans Pagel Date: Fri Jan 15 14:59:56 2021 +0100 refactoring commit 46798f194fdbb6b5781818e6386efc5c089b46cc Author: Hans Pagel Date: Fri Jan 15 11:07:17 2021 +0100 clean up commit ed7ebd39e13a1ed63931d19a08c2cc7a030f0e0a Author: Hans Pagel Date: Thu Jan 14 22:01:09 2021 +0100 refactoring commit 3d61a206c8f70601845da191e92693baf4cc7f28 Author: Hans Pagel Date: Thu Jan 14 21:49:08 2021 +0100 disable typescript errors for now commit cc2286d82ade7356fa998bfcd2dea2eafaa2f122 Author: Hans Pagel Date: Thu Jan 14 21:48:23 2021 +0100 code style commit bb9fb292693f929793663b83853083157c384136 Author: Hans Pagel Date: Thu Jan 14 21:45:20 2021 +0100 add a comment, set default class commit d547e74f092de6457a574b3d6b852bde3b408c8d Author: Hans Pagel Date: Thu Jan 14 21:41:03 2021 +0100 strange refactoring (wip) commit 99e415b4eba9e4fa704cbe77f053860bd7ae8b1b Author: Hans Pagel Date: Thu Jan 14 17:19:12 2021 +0100 add extension documentation page, refactoring commit ba585e6abe1b56c8c1fcd4e68057d967c23ad67e Author: Hans Pagel Date: Thu Jan 14 15:23:16 2021 +0100 refactoring commit 2981591b8b568e2b41f4f81930d67f75b0ffcd6d Author: Hans Pagel Date: Thu Jan 14 12:54:25 2021 +0100 refactoring commit 4083f3e3ac3f0d8ff54bae78ebb3e957f2f20309 Author: Hans Pagel Date: Thu Jan 14 12:52:49 2021 +0100 clean up commit 409a060be38d50fda542f988780481cffc94c54e Author: Hans Pagel Date: Thu Jan 14 12:33:54 2021 +0100 refactoring commit fb1d0dc46af4a067165dcca19c9b1ba8c7a5cfc9 Author: Hans Pagel Date: Thu Jan 14 12:12:58 2021 +0100 refactoring commit 6cba6e0d098c0f3d3d4ec1f0e74ab50aa7966d31 Author: Hans Pagel Date: Wed Jan 13 22:23:57 2021 +0100 refactoring commit 9f8b6ef0f5455e5c8b331258d9168d01c67e29b6 Author: Hans Pagel Date: Wed Jan 13 22:18:14 2021 +0100 clean up commit 514c4d08039352d9c96212116fc59cb676f86e0b Author: Hans Pagel Date: Wed Jan 13 22:15:18 2021 +0100 refactoring commit 3b0b99d0029130696b7651a9a417bcbee5a35b6d Author: Hans Pagel Date: Wed Jan 13 22:11:15 2021 +0100 remove version commit 64fc138d73d9981b8e187c703c68146be6276664 Author: Hans Pagel Date: Wed Jan 13 22:09:41 2021 +0100 code style commit cb42c8c504bc02c929bd041a1f1b87c3a8f068f8 Author: Hans Pagel Date: Wed Jan 13 22:07:05 2021 +0100 refactoring commit 4203615a35d34cd6988ac0377507f32f197860af Author: Hans Pagel Date: Wed Jan 13 21:47:16 2021 +0100 refactoring commit cf476d899193540013da22c4d078c1daca86f2d3 Author: Hans Pagel Date: Wed Jan 13 21:32:24 2021 +0100 add crappy styling commit 59a7639ee9c9fb7f3f57c376220a20baec93bba2 Author: Hans Pagel Date: Wed Jan 13 21:24:29 2021 +0100 add basic annotation plugin commit 8d2d9158cc1611da18432d76925c002731d51d09 Author: Hans Pagel Date: Wed Jan 13 16:19:15 2021 +0100 init new package --- .../Annotation/extension/AnnotationItem.ts | 10 ++ .../Annotation/extension/AnnotationPlugin.ts | 33 ++++ .../Annotation/extension/AnnotationState.ts | 95 ++++++++++++ .../Annotation/extension/annotation.ts | 70 +++++++++ .../Experiments/Annotation/extension/index.ts | 5 + .../Experiments/Annotation/index.spec.js | 7 + .../demos/Experiments/Annotation/index.vue | 87 +++++++++++ .../demos/Experiments/Comments/index.spec.js | 7 + docs/src/demos/Experiments/Comments/index.vue | 145 ++++++++++++++++++ .../src/docPages/api/extensions/annotation.md | 8 + docs/src/docPages/experiments.md | 2 + docs/src/docPages/experiments/annotation.md | 5 + docs/src/docPages/experiments/comments.md | 5 + docs/src/links.yaml | 7 + 14 files changed, 486 insertions(+) create mode 100644 docs/src/demos/Experiments/Annotation/extension/AnnotationItem.ts create mode 100644 docs/src/demos/Experiments/Annotation/extension/AnnotationPlugin.ts create mode 100644 docs/src/demos/Experiments/Annotation/extension/AnnotationState.ts create mode 100644 docs/src/demos/Experiments/Annotation/extension/annotation.ts create mode 100644 docs/src/demos/Experiments/Annotation/extension/index.ts create mode 100644 docs/src/demos/Experiments/Annotation/index.spec.js create mode 100644 docs/src/demos/Experiments/Annotation/index.vue create mode 100644 docs/src/demos/Experiments/Comments/index.spec.js create mode 100644 docs/src/demos/Experiments/Comments/index.vue create mode 100644 docs/src/docPages/api/extensions/annotation.md create mode 100644 docs/src/docPages/experiments/annotation.md create mode 100644 docs/src/docPages/experiments/comments.md diff --git a/docs/src/demos/Experiments/Annotation/extension/AnnotationItem.ts b/docs/src/demos/Experiments/Annotation/extension/AnnotationItem.ts new file mode 100644 index 00000000..56b85459 --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/extension/AnnotationItem.ts @@ -0,0 +1,10 @@ +export class AnnotationItem { + public id!: number + + public text!: string + + constructor(id: number, text: string) { + this.id = id + this.text = text + } +} diff --git a/docs/src/demos/Experiments/Annotation/extension/AnnotationPlugin.ts b/docs/src/demos/Experiments/Annotation/extension/AnnotationPlugin.ts new file mode 100644 index 00000000..290b9cef --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/extension/AnnotationPlugin.ts @@ -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 + }, + + }, +}) diff --git a/docs/src/demos/Experiments/Annotation/extension/AnnotationState.ts b/docs/src/demos/Experiments/Annotation/extension/AnnotationState.ts new file mode 100644 index 00000000..23f65823 --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/extension/AnnotationState.ts @@ -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) + } +} diff --git a/docs/src/demos/Experiments/Annotation/extension/annotation.ts b/docs/src/demos/Experiments/Annotation/extension/annotation.ts new file mode 100644 index 00000000..06c666b6 --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/extension/annotation.ts @@ -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: { + 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, + } +} diff --git a/docs/src/demos/Experiments/Annotation/extension/index.ts b/docs/src/demos/Experiments/Annotation/extension/index.ts new file mode 100644 index 00000000..7c86e27d --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/extension/index.ts @@ -0,0 +1,5 @@ +import { Annotation } from './annotation' + +export * from './annotation' + +export default Annotation diff --git a/docs/src/demos/Experiments/Annotation/index.spec.js b/docs/src/demos/Experiments/Annotation/index.spec.js new file mode 100644 index 00000000..6a218007 --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/index.spec.js @@ -0,0 +1,7 @@ +context('/api/extensions/annotations', () => { + before(() => { + cy.visit('/api/extensions/annotations') + }) + + // TODO: Write tests +}) diff --git a/docs/src/demos/Experiments/Annotation/index.vue b/docs/src/demos/Experiments/Annotation/index.vue new file mode 100644 index 00000000..9ab11811 --- /dev/null +++ b/docs/src/demos/Experiments/Annotation/index.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/docs/src/demos/Experiments/Comments/index.spec.js b/docs/src/demos/Experiments/Comments/index.spec.js new file mode 100644 index 00000000..6f90b595 --- /dev/null +++ b/docs/src/demos/Experiments/Comments/index.spec.js @@ -0,0 +1,7 @@ +context('/examples/annotations', () => { + before(() => { + cy.visit('/examples/annotations') + }) + + // TODO: Write tests +}) diff --git a/docs/src/demos/Experiments/Comments/index.vue b/docs/src/demos/Experiments/Comments/index.vue new file mode 100644 index 00000000..c2388200 --- /dev/null +++ b/docs/src/demos/Experiments/Comments/index.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/docs/src/docPages/api/extensions/annotation.md b/docs/src/docPages/api/extensions/annotation.md new file mode 100644 index 00000000..c65fea66 --- /dev/null +++ b/docs/src/docPages/api/extensions/annotation.md @@ -0,0 +1,8 @@ +# Annotation +TODO + +## Source code +[packages/extension-annotation/](https://github.com/ueberdosis/tiptap-next/blob/main/packages/extension-annotation/) + +## Usage + diff --git a/docs/src/docPages/experiments.md b/docs/src/docPages/experiments.md index 70f7d340..34e2966d 100644 --- a/docs/src/docPages/experiments.md +++ b/docs/src/docPages/experiments.md @@ -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) diff --git a/docs/src/docPages/experiments/annotation.md b/docs/src/docPages/experiments/annotation.md new file mode 100644 index 00000000..4d4ebbe5 --- /dev/null +++ b/docs/src/docPages/experiments/annotation.md @@ -0,0 +1,5 @@ +# Annotation + +⚠️ Experiment + + diff --git a/docs/src/docPages/experiments/comments.md b/docs/src/docPages/experiments/comments.md new file mode 100644 index 00000000..42fda436 --- /dev/null +++ b/docs/src/docPages/experiments/comments.md @@ -0,0 +1,5 @@ +# Comments + +⚠️ Experiment + + diff --git a/docs/src/links.yaml b/docs/src/links.yaml index e3176c41..d03fc02f 100644 --- a/docs/src/links.yaml +++ b/docs/src/links.yaml @@ -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