Storing plaintext representation in .toJSON

I’m working on a distributed application where documents are created and rendered on different systems with different versions of the code. For example a document created on one system (A) needs to be rendered on another system (B), but B isn’t running the latest code. This means that in some cases the document created on A will contain content that B doesn’t recognise.

However we are able to guarantee that both systems understand the structure of documents (we are using the builtin .toJSON representation) but won’t necessarily understand different node types. We’re able to tolerate different renderings of documents, and so we’d like to aim for having old renderers display a “degraded” representation, i.e. where unrecognised node types are rendered as plaintext, and marks are discarded.

The plan is to add an extra text attribute to newly added node types, and have it contain a plaintext representation of the node, i.e.

{
  "type": "mention",
  "attrs": {
    "id": "1234",
    "text": "@Brad"
  }
}

For mention-node-aware-renderers, a look-up for user 1234 is done and their name rendered, but for old renderers they would fall back to the convention of rendering the attrs.text value.

There’s a few consequences of this approach:

  • Need to decide whether attrs.text is updated in tandem with the document, or if it’s inserted as a step after (or replacing) .toJSON().
  • Introduces an inconsistency where text nodes have their content in text, but other nodes have their content in attrs.text.
  • Using an attribute rather than introducing a top level text property for every node adheres to the JSON structure (AFAICT text is reserved for text nodes only).
  • Need to define how whitespace is inserted between nodes (e.g. imagine introducing a list or table node type, and having rows render as a long string of text).

Does anyone have any thoughts on this? I’m interested in any feedback on this approach, if people have thought about or done something similar, see problems with this, or have better ideas.

Thanks