RFC: Deprecating prosemirror-schema-table and attribute constraints in schemas

The (for me) unexpected success of the new tables module, which I wrote for Atlassian and which they are now maintaining as an MIT-licensed module, has convinced me that this style of tables are the future, and my initial attempt, prosemirror-schema-table is a dead end.

Specifically, the initial module used schema constraints to enforce table shape (each row having the same number of cells). This is in principle a good idea – when you can encode constraints in your schema, you make sure that they are always enforced, and you never get documents that violate them. But in this case, it does have downsides — I had to add a bunch of extra, rather ad-hoc features to schema content expressions to support it, such nodes are a pain to work with (you often have to know the width of the table at points where it is tricky to do so), and it doesn’t generalize to tables that support rowspan/colspan (merged cells).

So the approach in the new module, where row- and column-spanning cells were a requirement, is to define a much simpler schema, which only says that table cells go in rows and rows in tables, and to enforce table shape constraints in the appendTransaction method of a table-editing plugin. This means that the document may, for some editing operations, end up with non-rectangular tables at the end of a transaction, but another transaction fixing that will be appended right away, before the content is even drawn to the screen. So if you had code that crashes when looking at a non-square table, that might be a problem, but in practice that doesn’t seem to really come up.

The new module thus support row- and column-spanning, along with cell selections (implemented using the extensible selection feature added a few months ago), providing a much better table editing experience.

Which leads me to think that no one really needs the old table module anymore, since there’s a much improved alternative available. So I plan to stop updating it.

That, in turn, means that it is possible that no one would be using the attribute-based content constraints anymore, since as a feature I don’t think they are much use for anything except that cell-count hack. So I would really like to drop that feature, making the constraint-enforcing code a little simpler and faster. Since that’s a relatively invasive change, it’d be something that would need to happen before 1.0.

Is anyone using attribute-based content constraints (the syntax where you refer to attributes by prefixing them with a dot in a content expression, or use [] syntax to constrain attributes themselves)? And if so, are you using it in a way that couldn’t be replaced by splitting your attribute-carrying node type into multiple types?


I’m using a content spec with that kind of constraints:

typeNameX[content_name=name1] typeNameY[content_name=name2] ...

However, i’m precisely rewriting that part and indeed the node type name could carry all that information already.

Great to see this being open sourced! :slight_smile:

We haven’t used attribute-based content constraints so far with the exception of using the prosemirror-schema-table.

Sounds like an interesting approach to use appendTransaction to enforce the table shape constraints! I have used this approach for much simpler constraints and it has worked very well for these. I’m happy to see this approach being used for more complex use cases as well.

What would be the things to be handled when migrating to the new tables module? These are the things I have noticed:

  • The table columns attribute is gone
  • The table row columns attribute is gone
  • Table cells have two new attributes colspan and rowspan (I’m not sure how these work, but I assume they would be set to 1 when migrating from an old table)
  • The new module does not define any custom steps

Looking at this, transforming old tables to new ones should be relatively straight forward in terms of content and model. Is there anything I am missing?

Yes, if you can convert your documents to fit the different schema style, you should be good to go I think.

1 Like

I’ve never needed to use the attribute-based content constraints, and would welcome the simplification (by removing them).

The first idea that comes to mind is a flag that is set somewhere that indicates the document is “irregular” or “intermediate” (i.e. not-schema-conforming). I haven’t thought too much about where best that should be, and haven’t done enough with documents that use the new “eventual consistency” approach to schema conformance to know for sure.

What ideas did you have for mitigating this problem?

My impression is that it is enough to simply know/document that a given constraint isn’t guaranteed to always be fulfilled, and write code that interacts with it defensively. For the table shape thing, that worked well so far.

(Another content-expression-related RFC is here)

This has been implemented!