Is it possible to alter split behavior of individual nodes / marks

Is there a way to define how blocks are split without overriding Enter keyboard shortcut or is that a recommended way ? For example with a following schema:

{
    article: {
      defining: true,
      group: "article",
      inline: false,
      content: "header",
      toDOM() { return ["article", {}, 0] },
      parseDOM: [{ tag: "article" }]
    },
    header: {
      marks: "_",
      group: "header",
      content: "text*",
      toDOM() { return ["header", {}, 0] },
      parseDOM: [{ tag: "header" }]
    },
    doc: {
      content: "article+"
    }

Hitting Enter in the header causes following error if there is no text after the caret or does nothing otherwise.

Uncaught TypeError: Cannot read property 'validContent' of undefined
    at Object.canSplit (file:///Users/gozala/Projects/Allusion/js/UI/Main.js:5055:134)
    at Array.splitBlock

Thanks

To be clear I believe it fails because ‘article’ can have only one header (not sure why it does not do the same when caret is in the middle of caret). What I would like to do is to add another article into doc but I’m not entirely sure how to do it.

This doesn’t really answer your question, but, we have hundreds of lines of code for defining functionality for selection handling and node manipulation with key inputs. However, that in itself may be a potentially unwanted answer to your question.

@JCHollett thanks for your response. To be clear I prefer to stay away from overriding keybindings as users may define their own bindings and then those don’t get handled by the overrides. So instead I would prefer some kind of hook I guess.

I also do see transactions in the my plugins state.apply but unfortunately it does not seems clear from it when split was attempted. I also hoped that schema somehow guides how nodes / marks are split.

Binding custom commands is the recommended way.

That should be fixed in prosemirror-commands 1.0.5 (the command will just not apply, rather than throwing an error, in cases like this where the parent block doesn’t allow any further content).

Thanks for responding @marijn. Would you please let me know what your thoughts are in regards to my concern about user defined key bindings ? What is the recommended way to handle this ?

Another though I had in this regard wouldn’t it make sense to include some metadata per transaction. To be more specific prosemirror-commands provides built-in commands (that actually could be chains of them) like backspace or for Enter key but in the plugin apply it’s often difficult to tell what are the changes or what caused them to happen. I think it could be very helpful if that semantic info was included in some way maybe Step instances could have some description field ? Or does that seem like wrong approach ?

On the same subject I also have being wondering what if keyboard handlers were just dispatching transactions describing that certain command was triggered (with a key-combo as cause) then actual execution of that command could be deferred after plugins gets a chance to override which command to execute (if any). That would greatly simplify overriding behavior of specific commands at certain states regardless of what triggered them a key combination or menu button (in which case cause would be a not a key combo but rather a menu item).

Also would you mind pointing out where arrow keys are wired up, I don’t seem to be able to pin point it.

Thanks

That’s not very common, and until beforeInput events become widespread, JavaScript simply doesn’t have a way to deal with it, so ProseMirror assumes standard key bindings.

The current avenue for this would be the meta fields in transactions, but built-in commands don’t add such info.

It is possible for user code to add an extra layer of indirection here, if it wants.

The browser handles them, so that we don’t need to reimplement the bidi algorithm in ProseMirror.

I suppose it should be possible to bind certain actions to keyboard shortcuts, and define that action specifically to handle things the way you want them to be handled. But, when it comes to unexpected results from basic prosemirror behavior, thats up to you to fix. Prosemirror does a good job at handling 60%+ of the cases. But, If you have some complicated schema requirements or complicated expectations of what should happen, there is no other choice but to define your actions specifically for each case.