initial commit

This commit is contained in:
cudr
2019-10-05 11:44:49 +03:00
commit a817eb1ceb
63 changed files with 1769 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
export const addAnnotation = (doc: any, op: any) => {
return doc
}
export const removeAnnotation = (doc: any, op: any) => {
return doc
}
export const setAnnotation = (doc: any, op: any) => {
return doc
}
export default {
add_annotation: addAnnotation,
remove_annotation: removeAnnotation,
set_annotation: setAnnotation
}

View File

@@ -0,0 +1,36 @@
import { Operation, Operations, SyncDoc } from '../model'
import node from './node'
import mark from './mark'
import text from './text'
import annotation from './annotation'
const setSelection = doc => doc
const setValue = (doc, op) => doc
const opType: any = {
...text,
...annotation,
...node,
...mark,
set_selection: setSelection,
set_value: setValue
}
export const applyOperation = (doc: SyncDoc, op: Operation): SyncDoc => {
try {
const applyOp = opType[op.type]
if (!applyOp) throw new TypeError('Invalid operation type!')
return applyOp(doc, op)
} catch (e) {
console.error(e)
return doc
}
}
export const applySlateOps = (doc: SyncDoc, operations: Operations) =>
operations.reduce(applyOperation, doc)

View File

@@ -0,0 +1,72 @@
import { getTarget } from '../path'
import { toSync } from '../utils'
import { SyncDoc } from '../model'
import { AddMarkOperation, RemoveMarkOperation, SetMarkOperation } from 'slate'
const findIndex = (node, mark) =>
node.marks.findIndex(m => m.type === mark.type)
export const addMark = (doc: SyncDoc, op: AddMarkOperation) => {
const node = getTarget(doc, op.path)
if (node.object !== 'text') {
throw new TypeError('cannot set marks on non-text node')
}
if (findIndex(node, op.mark) < 0) node.marks.push(toSync(op.mark.toJS()))
return doc
}
export const removeMark = (doc: SyncDoc, op: RemoveMarkOperation) => {
const node = getTarget(doc, op.path)
if (node.object !== 'text') {
throw new TypeError('cannot set marks on non-text node')
}
const index = findIndex(node, op.mark)
if (index >= 0) node.marks.splice(index, 1)
return doc
}
export const setMark = (doc: SyncDoc, op: SetMarkOperation) => {
const node = getTarget(doc, op.path)
if (node.object !== 'text') {
throw new TypeError('cannot set marks on non-text node')
}
const index = findIndex(node, op.properties)
if (index === -1) {
console.warn('did not find old mark with properties', op.properties)
if (!op.newProperties.type) {
throw new TypeError('no old mark, and new mark missing type')
}
node.marks.push({
object: 'mark',
type: op.newProperties.type,
...op.newProperties
})
} else {
node.marks[index] = {
object: 'mark',
...node.marks[index],
...op.newProperties
}
}
return doc
}
export default {
add_mark: addMark,
remove_mark: removeMark,
set_mark: setMark
}

View File

@@ -0,0 +1,107 @@
import { SyncDoc } from '../model'
import {
SplitNodeOperation,
InsertNodeOperation,
MoveNodeOperation,
RemoveNodeOperation,
MergeNodeOperation,
SetNodeOperation
} from 'slate'
import { getTarget, getParent } from '../path'
import { toJS, cloneNode, toSync } from '../utils'
export const insertNode = (doc: SyncDoc, op: InsertNodeOperation): SyncDoc => {
const [parent, index] = getParent(doc, op.path)
if (parent.object === 'text') {
throw new TypeError('cannot insert node into text node')
}
parent.nodes.splice(index, 0, toSync(op.node.toJS()))
return doc
}
export const moveNode = (doc: SyncDoc, op: MoveNodeOperation): SyncDoc => {
const [from, fromIndex] = getParent(doc, op.path)
const [to, toIndex] = getParent(doc, op.newPath)
if (from.object === 'text' || to.object === 'text') {
throw new TypeError('cannot move node as child of a text node')
}
to.nodes.splice(toIndex, 0, ...from.nodes.splice(fromIndex, 1))
return doc
}
export const removeNode = (doc: SyncDoc, op: RemoveNodeOperation): SyncDoc => {
const [parent, index] = getParent(doc, op.path)
if (parent.object === 'text') {
throw new TypeError('cannot remove node from text node')
}
parent.nodes.splice(index, 1)
return doc
}
export const splitNode = (doc: SyncDoc, op: SplitNodeOperation): SyncDoc => {
const [parent, index]: [any, number] = getParent(doc, op.path)
const target = parent.nodes[index]
const inject = cloneNode(target)
if (target.object === 'text') {
target.text.length > op.position &&
target.text.deleteAt(op.position, target.text.length - op.position)
op.position && inject.text.deleteAt(0, op.position)
} else {
target.nodes.splice(op.position, target.nodes.length - op.position)
op.position && inject.nodes.splice(0, op.position)
}
parent.nodes.insertAt(index + 1, inject)
return doc
}
export const mergeNode = (doc: SyncDoc, op: MergeNodeOperation) => {
const [parent, index]: [any, number] = getParent(doc, op.path)
const prev = parent.nodes[index - 1]
const next = parent.nodes[index]
if (prev.object === 'text') {
prev.text.insertAt(prev.text.length, ...toJS(next.text).split(''))
} else {
next.nodes.forEach(n => prev.nodes.push(cloneNode(n)))
}
parent.nodes.deleteAt(index, 1)
return doc
}
export const setNode = (doc: SyncDoc, op: SetNodeOperation) => {
const node = getTarget(doc, op.path)
const { type, data }: any = op.newProperties
if (type) node.type = type
if (node.object !== 'text' && data) node.data = data.toJSON()
return doc
}
export default {
insert_node: insertNode,
move_node: moveNode,
remove_node: removeNode,
split_node: splitNode,
merge_node: mergeNode,
set_node: setNode
}

View File

@@ -0,0 +1,24 @@
import { SyncDoc } from '../model'
import { InsertTextOperation, RemoveTextOperation } from 'slate'
import { getTarget } from '../path'
export const insertText = (doc: SyncDoc, op: InsertTextOperation): SyncDoc => {
const node = getTarget(doc, op.path)
node.text.insertAt(op.offset, op.text)
return doc
}
export const removeText = (doc: SyncDoc, op: RemoveTextOperation): SyncDoc => {
const node = getTarget(doc, op.path)
node.text.deleteAt(op.offset, op.text.length)
return doc
}
export default {
insert_text: insertText,
remove_text: removeText
}