Are CodeMirror style linked documents possible?

I’m just reading about ProseMirror for last day. May very well be missing the obvious. Depressing (in a good way mostly, thanks for making it open source) all the cool stuff… I work on my own editors and I’m just not this smart I think :slight_smile:

Anyway, I’m interested in creating multiple views of the same underlying document model. For example one editor would view the entire document, while another would be focused into a particular section of that document.

In CodeMirror you can do this by creating a linked document. I’m wondering if ProseMirror has a similar concept? I’ve looked around but can’t seem to find it.

If this isn’t already possible can anyone speculate how hard it would be to implement? At a high level I imagine it might be implemented by:

  1. Create and editor with a document

  2. Choose a range of nodes from the document that you want to view as sub-document.

  3. Create new sub-document with those nodes as children and also record the start offset of those nodes from the original document.

  4. When steps happen in sub-document adjust them by that start offset and also apply them to original document.

  5. Watch for steps in original document and adjust it’s start offset position as needed. And for any steps that effect sub-document content, map and apply those steps.

Links, thoughts, suggestions are all appreciated.

Thanks, Jesse

This works very differently in ProseMirror, but you can do something like it. You take all editing steps that occur in the sub-view, and apply them to the larger document with a suitable offset, and, at the same time, keep the sub-document in sync with a part of the larger document (either using steps, in which case you have to take care not to apply steps twice, or by replacing the sub-document every time it gets out of sync with the bigger document). The footnote and code editor examples do something like that, though they use a node view inside the bigger editor rather than a separate editor for the sub-view.

3 Likes

I was also wondering if there was a simple way for ProseMirror to merge a modified child document back into its parent after “detaching” it with steps. (For focus into a smaller document section, as well). Did you ever find a solution?

Here are ideas I had:

  • If you just need focus, it might be better to always hold the entire document and just hide the unfocused parts with something like decorations.
  • If you also need a simultaneous view with the entire document, you can link two separate documents with the collab module.

Similar question here: I want to create a page that contains an editor, and that I can split into two (or more) duplicates of that editor so I can scroll to different parts of the document in the different splits. My hope was to create duplicate EditorViews to accomplish that, each working on the same EditorState.

Following the ProseMirror Guide example , something like:

let views = [createView(viewRef1), createView(viewRef2)]

function createView(ref:HTMLDivElement) {
   return new EditorView(ref, {
      state: appState.editor,
      dispatchTransaction(transaction:Transaction) {
         update({type: "EDITOR_TRANSACTION", transaction})
      }
   })
}

// A crude app state update function, which takes an update object,
// updates the `appState`, and then refreshes the UI.
function update(event) {
   if (event.type == "EDITOR_TRANSACTION")
      appState.editor = appState.editor.apply(event.transaction)
   else if (event.type == "SCORE_POINT")
      appState.score++
   draw()
}

// An even cruder drawing function
function draw() {
   document.querySelector("#score").textContent = `${appState.score}`
   views.forEach(view => view.updateState(appState.editor))
}

@marijn, your response to @jessegrosjean seems to imply that there must be a one-to-one relationship between a view and a state. Especially for large documents that sound very resource heavy, hence I am assuming I may have misunderstood something.

Much appreciate your effort and thoughts in architecting and creating prosemirror!

The cost of an editor state dwarfs in comparison to the cost of the DOM representing it, and you’ll need that anyway if you have multiple views. Also, if you create the states from the same document instance, states can even share (unmodified) document structure.