Delete node and automatically remove empty wrappers

Say I have a node type box, the content of which is chocolate+. What the chocolate contains is not important for the question, other than to assume it’s a kind of node that PM can create automatically. Now say I have a box with one chocolate inside. If I remove the last chocolate, PM will create a new chocolate and insert it automatically, in order not to violate the one-or-more constraint. Right?

An alternative way to keep the doc valid, would be to remove the box along with the last chocolate. For my use-case, that’s what I need.

Is there any way to configure the schema such that that would happen?

Alternatively, how hard would it be to implement that as a generic operation? Something like removeNodeAndInvalidEmptyWrappers. Any advice on how to code that?

Thanks : )

Quick follow up - I think this should be fairly simple:

  • Is the node to be removed an only child?
    • Yes? Is an empty fragment valid content for the parent?
      • No? Recurse with the parent as the node to be removed, and return
  • (Didn’t return) Just remove the node

I think this should be done on the level of the commands that perform the deletions. Transform.deleteRange (and things built on top of it, like selection deletion) should already do this (unless the wrapper is marked as defining). How is the user performing the deletion in this case?

Aha - that is my problem. Does this behaviour come from definingAsContext or definingForContent⁠?

I think I’m doing fairly unconventional things with my schema, and I’m often not super confident how to use these settings for my situation. I end up doing a bit of trial and error.

On closer look, it seems deletion only checks isolating, not defining.

Understanding the implication of these schema switches can be a little difficult. I wonder if there is a better way.

Ultimately, there are a whole bunch of decision points in the implementation of the transformation steps, where the value of these flags are checked. One way to look at the purpose of code, isolating, and the three ‘defining’ flags, is to group these decision points under meaningful names. That keeps NodeSpec smaller, but it can be obscure. For example code “causes some commands to behave differently”.

In the case of code that’s probably fine, because it’s very clear what code means, but for isolating and defining it’s much less clear.

Would it make things more concrete if each individual decision point was exposed as a named config option? For example, the behaviour in this thread could be autoDeleteEmptyWrappers. The meaning of isolating/defining could then be made precise: they would simply be named presets for the more detailed options. That would also be backwards compatible. It’s sort of an extension of the idea we already have with definingAsContext and definingForContent.

For people (like me) working with unusual schemas, I think this could be really helpful. I often feel like I’m trying to get at those underlying decisions, trying various combinations of the config flags to get the behaviour I want. The tricky part (and maybe tricky enough to kill the whole idea) might be finding understandable and not ridiculously long names for the various decisions.