xylk / prosemirror-firebase

ProseMirror + Firebase Realtime Database
MIT License
31 stars 11 forks source link
firebase prosemirror

prosemirror-firebase

Collaborative editing for ProseMirror using Firebase's Realtime Database. Features timestamped and attributed changes, version checkpointing, selection tracking, and more.

usage

Assumes familiarity with ProseMirror and Firebase.

Call new FirebaseEditor with an object containing:

Returns a Promise that resolves when the editor is ready (when existing content has been loaded and an editor view has been created). The resolved value is an object containing the properties and methods of the editor:

basic

new FirebaseEditor({
    firebaseRef: /*database.Reference*/,
    stateConfig: {
        schema: /*Schema*/,
    },
    view({ stateConfig, updateCollab }) {
        let view = new EditorView(/*dom.Node*/, {
            state: EditorState.create(stateConfig),
            dispatchTransaction(transaction) {
                let newState = view.state.apply(transaction)
                view.updateState(newState)
                updateCollab(transaction, newState)
            },
        })
        return view
    },
})

cursors and selections

function stringToColor(string, alpha = 1) {
    let hue = string.split('').reduce((sum, char) => sum + char.charCodeAt(0), 0) % 360
    return `hsla(${hue}, 100%, 50%, ${alpha})`
}

new FirebaseEditor({
    /*...*/
    view({ stateConfig, updateCollab, selections }) {
        let view = new EditorView(/*dom.Node*/, {
            /*...*/
            decorations({ doc }) {
                return DecorationSet.create(doc, Object.entries(selections).map(
                    function ([ clientID, { from, to } ]) {
                        if (from === to) {
                            let elem = document.createElement('span')
                            elem.style.borderLeft = `1px solid ${stringToColor(clientID)}`
                            return Decoration.widget(from, elem)
                        } else {
                            return Decoration.inline(from, to, {
                                style: `background-color: ${stringToColor(clientID, 0.2)};`,
                            })
                        }
                    }
                ))                  
            },
        })
        return view
    },
})

ready

new FirebaseEditor({
    /*...*/
}).then(({ view, selections, destroy }) => {
    console.log('editor ready')
}).catch(console.error)

license

MIT license.