Replace Enter with Shift+Enter

Hello everyone! I have an Angular Web App that uses Kendo Editor (which uses ProseMirror), and since pressing Enter adds too much space under the paragraph when I “convert” the text to PDF, whereas Shift+Enter doesn’t, I’m looking for a way to intercept every Enter keypress and treat it as a Shift-Enter keypress.

I contacted Telerik Support and they suggested me to use their plugins property. In this page for example they created a plugin that searches on Google the selected text.

My html is:

<kendo-editor [plugins]="myPlugins">

And my TS, with my attempt of doing what I need, is:

  myPlugins (defaultPlugins: Plugin[]): Plugin[] { 
    let shiftEnterPlugin = new Plugin({
        keymap: keymap({
          Enter: (state, dispatch) => {
            const tr = state.tr.insertText("\n");
            tr.setSelection(state.selection.anchor + 1);
            dispatch(tr);
            return true;
        },
      })
    });

    return [...defaultPlugins, shiftEnterPlugin];
  }

I’m getting an error because the argument of setSelection is of type number and not Selection. Am I close to the solution or is my approach wrong?

The link provided above has a StackBlitz that can be modified if it helps you to help me.

Thanks in advance

That seems like a styling issue, more than a document structure issue.

If you really want to approach the problem in this way, you don’t need to write a plugin to change a key binding though, just adding a keymap with higher precedence than the default keymap should do the trick (assuming the context lets you do that).

Telerik HTMLTextBox, which is used in the PDF making, doesn’t have a margin property that can be set to 0 to avoid the p having space under it, and using negative padding (which is the suggested solution on their forums), can’t be used in my case. I’m reading keymap documentation but I don’t understand how to use it outside of a Plugin context: doesn’t it return a Plugin?

I made a StackBlitz

I’m struggling to understand what’s actually being converted to PDF. (That’s not part of the StackBlitz, I guess). If it’s the view (you’re essentially “printing” the contenteditable) then you should probably adjust the styles in the browser to reflect what you’re trying to do. If it’s the model then it’s an issue of changing how it gets mapped to PDF content. Changing keybindings is not a good solution, because you’re just introducing junk into your model that doesn’t express itself in any output. It’s likely to have edge-cases (anywhere a new paragraph is created without using the Enter key).

Hello, thanks for your reply-

The text inside the editor is sent to the Back End of my app, that uses Telerik Reporting tool to generate a PDF containing various info. This tool has a HTMLTextBox that can only deal with a subset of css properies

This is what I typed: ‘Test1’, Enter, ‘normalreturn’, Enter, Enter, ‘Test2’, Shift+Enter, ‘shiftreturn’ and this is the genrated HTML:

  <p style="margin: 0px; padding: 0px;"><span style="font-size: 12px; font-family: Arial; margin: 0px; padding: 0px;">Test1</span></p>
  <p style="margin: 0px; padding: 0px;"><span style="font-size: 12px; font-family: Arial; margin: 0px; padding: 0px;">normalreturn</span></p>
  <p style="margin: 0px; padding: 0px;"><br class="ProseMirror-trailingBreak"></p>
  <p style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-size: 14px; font-family: Arial;">Test2<br>shiftreturn</span></p>

You won’t see the padding and margin in my StackBlitz, it’s simpler that the one in my app that uses regex ad other stuff. But you can see that if you press enter or shift+enter, the spacing of the paragraphs differs.

This margin: 0px can’t be intercepted by HTMLTextbox (whereas padding can, hence why their suggestions is to use negative padding, even if it doesn’t work in my case). With shift+enter, I don’t have this problem so I want to replace Enter with Shift+Enter

I suppose if it were up to me I’d be tempted to serialize your ProseMirror data differently to send to the backend than what you’re sending to the view. Then you could simply not create <p> tags at all but just put <br /> tags in between your paragraphs.

The problem with approaching this from the level of keybindings/commands is that you have to think about ALL of the ways paragraphs can be created. It will be especially hard at the level of parsing pasted hypertext.

That is true, however this is the solution my boss wants and so I have to go on with it. My problem right now is how to call the setPosition on my transaction and pass to it the anchor+1, which is a number and not a Selection.

My current attempt is:

    myPlugins(defaultPlugins: Plugin[]): Plugin[] {
      console.log('Inside myPlugins()');
      let shiftEnter: Plugin = keymap({
        Enter: (state, dispatch) => {
          console.log('state:', state);
          console.log('dispatch:', dispatch);

          const tr = state.tr.insertText("\n");
          const newPos = tr.selection.anchor+1;
          tr.setSelection(TextSelection.create(tr.doc, newPos));

          dispatch(tr);
          return true;
        },
      });
  }

Don’t use \n characters in non-code blocks. Surely your schema has a hard_break-like node to insert instead. tr.replaceSelectionWith should make this really easy to do.

Hello, my schema has a hard_break node type, but I don’t know how to create a node with that type…

Something like this maybe?

 myPlugins(defaultPlugins: Plugin[]): Plugin[] {
      let shiftEnter: any = keymap({
        Enter: (state, dispatch) => {
          console.log('state', state);
          const myNode = schema.nodes.hard_break.create();
          const tr = state.tr.replaceSelectionWith(myNode)
          dispatch(tr);
          
          return true;
        },
      });