insertHorizontalRule

How insertHorizontalRule inputType inserts horizontal rule (hr) elements and varies across browsers.

Overview

The insertHorizontalRule inputType is triggered when the user inserts a horizontal rule (typically via toolbar or programmatically). The browser inserts an <hr> element at the current cursor position.

Basic Behavior

Scenario: Cursor in middle of paragraph

Before (Cursor at position 5)

HTML:
<p>Hello|world</p>

After insertHorizontalRule

HTML:
<p>Hello</p>
<hr>
<p>world</p>
Paragraph split, <hr> inserted between

Browser-Specific Behavior

Chrome/Edge

  • Inserts <hr> element
  • May split current paragraph if cursor is in middle
  • Creates new paragraph after <hr> if needed

Firefox

  • Similar behavior to Chrome
  • May handle paragraph splitting differently

Safari

  • Horizontal rule insertion may differ
  • May use different element structure

Editor-Specific Handling

Different editor frameworks handle horizontal rule insertion differently. Here's how major editors implement insertHorizontalRule:

Slate.js

Horizontal Rule Insertion

Slate inserts horizontal rule as a block element:

    import { Editor, Transforms, Element } from 'slate';

element.addEventListener('beforeinput', (e) => {
  if (e.inputType === 'insertHorizontalRule') {
    e.preventDefault();
    
    // Insert horizontal rule block
    Transforms.insertNodes(editor, {
      type: 'horizontal-rule',
      children: [],
    });
    
    // Insert new paragraph after hr
    Transforms.insertNodes(editor, {
      type: 'paragraph',
      children: [{ text: '' }],
    });
  }
});
  
  • Block element: Horizontal rule is represented as a block element in Slate.
  • Transforms.insertNodes: Inserts horizontal rule block at selection.
ProseMirror

Horizontal Rule Insertion

ProseMirror inserts horizontal rule node:

    import { schema } from './schema';

view.dom.addEventListener('beforeinput', (e) => {
  if (e.inputType === 'insertHorizontalRule') {
    e.preventDefault();
    const { state, dispatch } = view;
    
    // Insert horizontal rule node
    const hrNode = schema.nodes.horizontal_rule.create();
    const tr = state.tr.replaceSelectionWith(hrNode);
    
    // Insert paragraph after if needed
    const paragraph = schema.nodes.paragraph.create();
    tr.insert(tr.selection.after, paragraph);
    
    dispatch(tr);
  }
});
  
  • Node creation: Creates horizontal rule node from schema.
  • replaceSelectionWith: Replaces selection with horizontal rule.
Draft.js

Horizontal Rule Insertion

Draft.js uses block type for horizontal rule:

    import { EditorState, Modifier } from 'draft-js';

function handleInsertHorizontalRule(editorState) {
  const contentState = editorState.getCurrentContent();
  const selection = editorState.getSelection();
  
  // Create horizontal rule block
  const newContentState = Modifier.splitBlock(contentState, selection);
  const newSelection = newContentState.getSelectionAfter();
  
  // Set block type to horizontal-rule
  const blockMap = newContentState.getBlockMap();
  const block = blockMap.get(newSelection.getStartKey());
  const newBlock = block.merge({ type: 'horizontal-rule' });
  
  const finalContentState = newContentState.merge({
    blockMap: blockMap.set(newSelection.getStartKey(), newBlock),
  });
  
  return EditorState.push(
    editorState,
    finalContentState,
    'insert-fragment'
  );
}
  
  • Block type: Uses block type (e.g., 'horizontal-rule') for horizontal rule.
  • splitBlock: Splits current block and creates horizontal rule block.

Related resources