text {inline{@attr: attr text}: tagged text} text
text {block:}
{@attr: attr text}
tagged text
tagged text
text {literal=}
{@attr: attr text}
{ignored: literal text}
literal text
I would love to enhance the textual representation with what ProseMirror has to offer. First I looked at decorators, but they seem more appropriate for things like syntax highlighting. What I really am after is the ability to style my tags with arbitrary HTML, but continue the editor as it were, in some fragments. So I created a schema instead, which mostly worked. However I then found the issue about inline nodes with content. So how does that affect my inline tags, which in turn can have other inline tags within them? Does this mean I cannot implement what I hoped to implement with ProseMirror?
And if nested inline nodes are no longer a problem, how do I best approach styling them? Say my inline tag has the schema content label attrTag* (markedText | inlineTag)*. What if I want something after the label, but only for inline tags. I do not see how I can achieve this with the array notation, so I tried creating a DOM node instead, but that seems the wrong approach when you want something that is editable or has children. I also looked at node views, but they too seem made for just inline leaf nodes.
I love to be proved wrong, but it seems I am out of luck and my use case simply is not supported. If this is the case, does anyone have a suggestion of potential alternatives that I could use?
grayen:
So how does that affect my inline tags, which in turn can have other inline tags within them? Does this mean I cannot implement what I hoped to implement with ProseMirror?
The current story for non-leaf inline nodes is that they are supported, but you have to define a custom node view for them, and you are responsible for creating a piece of DOM that will act appropriately when edited. This approach sounds like the most appropriate one for your use case – define your tags as nodes in your schema, and write a node view that renders them, either embedding another ProseMirror instance for the content, or allowing their child nodes to be rendered by the outer ProseMirror, you’ll have to see what works best.
marijn:
write a node view that renders them, either embedding another ProseMirror instance for the content, or allowing their child nodes to be rendered by the outer ProseMirror, you’ll have to see what works best.
A node view with a ProseMirror instance embedded within, I understand, that basically is what you did in the footnote example, but allowing a node view to render their children by the outer ProseMirror instance, I do not understand. Is there an example of this as well? From what I understand a node view is an escape from normal rendering, so it is more flexible, but you are responsible for updating ProseMirror with the changes made inside the node view (e.g. the CodeMirror example). So I am unsure how to approach rendering the nodes by the outer ProseMirror instance in the case of a node view.
I thought embedding an instance would be too expensive, but thinking about it some more, I now see how I would only ever need one embedded instance. I could just remove the embedded instance once I am done editing a fragment. I just have to make sure that the embedded instance correctly communicates every change back to the outer instance. That approach would even work for my CodeMirror version. Nevertheless I would love to know what you meant with letting the outer instance render the child nodes.
PS: Just wanted to let you know I respect and love your work! To be honest I first wanted to use Ace instead of CodeMirror and SlateJS instead of ProseMirror, but in both cases I ended up with the latter because your projects are just more pragmatic and have APIs that do not hide stuff, are feature rich, and which allow you to cater it to almost any use case. And maybe even most importantly have an author that is really committed!
grayen:
So I am unsure how to approach rendering the nodes by the outer ProseMirror instance in the case of a node view.
If you provide a contentDOM property on your node view, content rendering and updating will be handled by the library.
grayen:
I thought embedding an instance would be too expensive,
ProseMirror instances are relatively lightweight (compared to things like CodeMirror), but yeah, depending on how many of these you have, you might want to optimize this.
grayen:
To be honest I first wanted to use Ace instead of CodeMirror and SlateJS instead of ProseMirror, but in both cases I ended up with the latter
That’s really great to hear!
marijn:
If you provide a contentDOM property on your node view, content rendering and updating will be handled by the library.
I seemed to have misunderstood that property, but after rereading the description, I understand it to mean that it is like being able to define what the 0 is in array notation, i.e. what DOM node of the DOM nodes you use in the node view will hold the DOM of the children.
It still feels somewhat non-intuitive to me, to only have one location that can hold children, because if some children are very coupled to their parent (semantically and in the way they are rendered) and you could want to add some logic that involves both the parent node and such a child node, you would want to place such logic in the parent node, but in the current situation the parent and child are worlds on their own, so you have to somehow reintroduce this relation between them with workarounds. In my example the label and attrTag* are tightly coupled to the concept of a tag, only the tag contents (markedText | inlineTag)* nicely fit with the concept of contentDOM. I hope you understand what I am getting at. Anyway I can think of a few ways to work around this if this really becomes an issue in my use case.
It is clear to me know that there is nothing fundamental keeping me from implementing what I hope to implement with ProseMirror, it will just require some experimentation to find out what approach works out best. Thank you!