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.