mirror of
https://github.com/ueberdosis/tiptap.git
synced 2025-01-18 06:03:22 +08:00
annotations: refactor annotation representation
This commit is contained in:
parent
10fdb79a9d
commit
b7f25e131c
@ -1,10 +1,37 @@
|
||||
export class AnnotationItem {
|
||||
public id!: string
|
||||
private decoration!: any
|
||||
|
||||
public content!: string
|
||||
constructor(decoration: any) {
|
||||
this.decoration = decoration
|
||||
}
|
||||
|
||||
constructor(id: string, content: string) {
|
||||
this.id = id
|
||||
this.content = content
|
||||
get id() {
|
||||
return this.decoration.type.spec.id
|
||||
}
|
||||
|
||||
get from() {
|
||||
return this.decoration.from
|
||||
}
|
||||
|
||||
get to() {
|
||||
return this.decoration.to
|
||||
}
|
||||
|
||||
get content() {
|
||||
return this.decoration.type.spec.content
|
||||
}
|
||||
|
||||
get HTMLAttributes() {
|
||||
return this.decoration.type.attrs
|
||||
}
|
||||
|
||||
toString() {
|
||||
return JSON.stringify({
|
||||
id: this.id,
|
||||
content: this.content,
|
||||
from: this.from,
|
||||
to: this.to,
|
||||
HTMLAttributes: this.HTMLAttributes,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { Decoration, DecorationSet } from 'prosemirror-view'
|
||||
import { ySyncPluginKey, relativePositionToAbsolutePosition, absolutePositionToRelativePosition } from 'y-prosemirror'
|
||||
import { AddAnnotationAction, DeleteAnnotationAction } from './annotation'
|
||||
import { AnnotationPluginKey } from './AnnotationPlugin'
|
||||
import { AnnotationItem } from './AnnotationItem'
|
||||
|
||||
export interface AnnotationStateOptions {
|
||||
HTMLAttributes: {
|
||||
@ -21,11 +22,16 @@ export class AnnotationState {
|
||||
this.options = options
|
||||
}
|
||||
|
||||
randomId() {
|
||||
// TODO: That seems … to simple.
|
||||
return Math.floor(Math.random() * 0xffffffff).toString()
|
||||
}
|
||||
|
||||
findAnnotation(id: string) {
|
||||
const current = this.decorations.find()
|
||||
|
||||
for (let i = 0; i < current.length; i += 1) {
|
||||
if (current[i].spec.data.id === id) {
|
||||
if (current[i].spec.id === id) {
|
||||
return current[i]
|
||||
}
|
||||
}
|
||||
@ -35,14 +41,14 @@ export class AnnotationState {
|
||||
const ystate = ySyncPluginKey.getState(state)
|
||||
const { type, binding } = ystate
|
||||
const { map } = this.options
|
||||
const { from, to, data } = action
|
||||
const { from, to, content } = action
|
||||
const absoluteFrom = absolutePositionToRelativePosition(from, type, binding.mapping)
|
||||
const absoluteTo = absolutePositionToRelativePosition(to, type, binding.mapping)
|
||||
|
||||
map.set(data.id, {
|
||||
map.set(this.randomId(), {
|
||||
from: absoluteFrom,
|
||||
to: absoluteTo,
|
||||
data,
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
@ -53,7 +59,9 @@ export class AnnotationState {
|
||||
}
|
||||
|
||||
annotationsAt(position: number) {
|
||||
return this.decorations.find(position, position)
|
||||
return this.decorations.find(position, position).map(decoration => {
|
||||
return new AnnotationItem(decoration)
|
||||
})
|
||||
}
|
||||
|
||||
updateDecorations(state: EditorState) {
|
||||
@ -65,16 +73,16 @@ export class AnnotationState {
|
||||
Array
|
||||
.from(map.keys())
|
||||
.forEach(id => {
|
||||
const dec = map.get(id)
|
||||
const from = relativePositionToAbsolutePosition(doc, type, dec.from, binding.mapping)
|
||||
const to = relativePositionToAbsolutePosition(doc, type, dec.to, binding.mapping)
|
||||
const decoration = map.get(id)
|
||||
const from = relativePositionToAbsolutePosition(doc, type, decoration.from, binding.mapping)
|
||||
const to = relativePositionToAbsolutePosition(doc, type, decoration.to, binding.mapping)
|
||||
|
||||
if (!from || !to) {
|
||||
return
|
||||
}
|
||||
|
||||
return decorations.push(
|
||||
Decoration.inline(from, to, HTMLAttributes, { data: dec.data }),
|
||||
Decoration.inline(from, to, HTMLAttributes, { id, content: decoration.content }),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,23 +1,23 @@
|
||||
import * as Y from 'yjs'
|
||||
import { Extension, Command } from '@tiptap/core'
|
||||
import { AnnotationItem } from './AnnotationItem'
|
||||
import { AnnotationPlugin, AnnotationPluginKey } from './AnnotationPlugin'
|
||||
|
||||
function randomId() {
|
||||
// TODO: That seems … to simple.
|
||||
return Math.floor(Math.random() * 0xffffffff).toString()
|
||||
}
|
||||
|
||||
export interface AddAnnotationAction {
|
||||
type: 'addAnnotation',
|
||||
content: any,
|
||||
from: number,
|
||||
to: number,
|
||||
data: AnnotationItem,
|
||||
}
|
||||
|
||||
export interface UpdateAnnotationAction {
|
||||
type: 'updateAnnotation',
|
||||
id: string,
|
||||
content: any,
|
||||
}
|
||||
|
||||
export interface DeleteAnnotationAction {
|
||||
id: string,
|
||||
type: 'deleteAnnotation',
|
||||
id: string,
|
||||
}
|
||||
|
||||
export interface AnnotationOptions {
|
||||
@ -89,10 +89,17 @@ export const Annotation = Extension.create({
|
||||
type: 'addAnnotation',
|
||||
from: selection.from,
|
||||
to: selection.to,
|
||||
data: new AnnotationItem(
|
||||
randomId(),
|
||||
content,
|
||||
),
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
updateAnnotation: (id: string, content: any): Command => ({ dispatch, state }) => {
|
||||
if (dispatch) {
|
||||
state.tr.setMeta(AnnotationPluginKey, <UpdateAnnotationAction>{
|
||||
type: 'updateAnnotation',
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,14 @@
|
||||
comment
|
||||
</button>
|
||||
<editor-content :editor="editor" />
|
||||
<div v-for="comment in comments" :key="comment.type.spec.data.id">
|
||||
{{ comment.type.spec.data }}
|
||||
<div v-for="comment in comments" :key="comment.id">
|
||||
{{ comment }}
|
||||
|
||||
<button @click="deleteComment(comment.type.spec.data.id)">
|
||||
<button @click="updateComment(comment.id)">
|
||||
update
|
||||
</button>
|
||||
|
||||
<button @click="deleteComment(comment.id)">
|
||||
remove
|
||||
</button>
|
||||
</div>
|
||||
@ -23,11 +27,6 @@
|
||||
comment
|
||||
</button>
|
||||
<editor-content :editor="anotherEditor" />
|
||||
|
||||
<h2>
|
||||
Y.js document
|
||||
</h2>
|
||||
{{ json }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -108,19 +107,22 @@ export default {
|
||||
|
||||
this.editor.commands.addAnnotation(content)
|
||||
},
|
||||
addAnotherComment() {
|
||||
const content = prompt('Comment', '')
|
||||
updateComment(id) {
|
||||
const comment = this.comments.find(item => {
|
||||
return id === item.id
|
||||
})
|
||||
|
||||
this.anotherEditor.commands.addAnnotation(content)
|
||||
const content = prompt('Comment', comment.content)
|
||||
|
||||
this.editor.commands.updateAnnotation(id, content)
|
||||
},
|
||||
deleteComment(id) {
|
||||
this.editor.commands.deleteAnnotation(id)
|
||||
},
|
||||
},
|
||||
addAnotherComment() {
|
||||
const content = prompt('Comment', '')
|
||||
|
||||
computed: {
|
||||
json() {
|
||||
return this.ydoc.toJSON()
|
||||
this.anotherEditor.commands.addAnnotation(content)
|
||||
},
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user