The feature I’m building relies on having a data model with top-level blocks of a few different types:
rich text, containing an HTML string with textual content with formatting (paragraphs, lists, and inline formatting in them)
image, referencing an associated image
a few other types that also have some associated attributes
My first idea for the editor configuring this feature was to use my own code managing those top-level blocks, and then using Prosemirror only for the content of “rich text” blocks, with a separate Prosemirror instance for each of them.
However, I’m wondering whether there would be a way to build this inside Prosemirror instead, to provide a better UX (single undo history, possibility to split a rich text block into 2 to add another block between them, single menu bar at the top as it would then be a single editor, …). This leads to several questions about how to do it:
how can I get/set the data based on JSON containing a list of blocks, where my rich text blocks contain an HTML string (and not JSON objects for child nodes) ?
is it possible for Prosemirror to automatically wrap content in a “rich text” block when typing content after a block of another type (the “rich text” block being the only kind of block allowing arbitrary textual content) ?
Yes, this should work very well as a ProseMirror schema. You’ll have to define node types for your non-text blocks, so that you can express them as ProseMirror nodes and include them in the editor’s document model. When the user starts typing in a place that doesn’t currently have a textblock, it will create one. You may be able to use the gapcursor plugin to allow cursors between images and other non-textblock nodes.
And what about my first question ? AFAIU, schema.nodeFromJson expects a JSON representing the structure of nodes, which would imply nested nodes for the “rich text” rather than an HTML string for the block content, while DOMParser would expect HTML for the whole document, and would also produce HTML when serializing (which would force my backend to parse the top-level blocks again).
Is there a way to parse/serialize the content of “rich text” blocks from/into HTML, while using JSON for the list of top-level blocks and their attributes (for other types) ?
I’d recommend storing the text nodes as ProseMirror JSON as well if you can. But DOMParser/DOMSerializer can convert to and from HTML if that’s not an option.
Storing the text nodes as ProseMirror JSON would be complex for me, because it would require me to reimplement the Prosemirror serialization in my PHP backend code when consuming this content to use it in my feature.
Is it possible to use DOMParser and DOMSerializer to convert only the child nodes of my “rich text” blocks or do they work only for the whole document ? (my previous usage of ProseMirror on a different use case already uses them for the whole document)
I feel like looking at the actual documentation I linked would answer this question. You can serialize a single node, and you can pass a specific topNode option to the parser to parse the content as if it lives inside that node instead of the schema’s document node. You can also mangle the JSON or use only parts of it if that is easier.
Looking at the documentation, I feel like serializeFragment might fit my need of getting the HTML for the children of my “rich text” node. Is there a way in DOMParser to parse a fragment ? Is this what topNode would allow ?