import { ApplySchemaAttributes , CommandFunction , ErrorConstant , extension , ExtensionTag , InputRule , invariant , isEmptyBlockNode , isNodeSelection , NodeExtension , NodeExtensionSpec , nodeInputRule , NodeSpecOverride , Transaction , } from '@remirror/core' ; import { TextSelection } from '@remirror/pm/state' ; export interface HorizontalRuleOptions { default insertionNode ? : string | false ; } /**
 * Adds a horizontal line to the editor.
 */ @ extension < HorizontalRuleOptions > ( { defaultOptions : { insertionNode : 'paragraph' } , } ) export class HorizontalRuleExtension extends NodeExtension < HorizontalRuleOptions > { get name ( ) { return 'horizontalRule' as const ; } createTags ( ) { return [ ExtensionTag . Block ] ; } createNodeSpec ( extra , override ) { return { ... override , attrs : extra . defaults ( ) , parseDOM : [ { tag : 'hr' , getAttrs : extra . parse } , ... ( override . parseDOM ?? [ ] ) ] , toDOM : ( node ) => [ 'hr' , extra . dom ( node ) ] , } ; } createCommands ( ) { return { /**
             * Inserts a horizontal line into the editor.
             */ insertHorizontalRule : ( ) : CommandFunction => ( props ) => { const { tr , dispatch } = props ; const $pos = tr . selection . $anchor ; const initialParent = $pos . parent ; if ( initialParent . type . name === 'doc' || initialParent . isAtom || initialParent . isLeaf ) { return false ; } if ( ! dispatch ) { return true ; } const shouldDuplicateEmptyNode = tr . selection . empty && isEmptyBlockNode ( initialParent ) ; if ( shouldDuplicateEmptyNode ) { tr . insert ( $pos . pos + 1 , initialParent ) ; } tr . replaceSelectionWith ( this . type . create ( ) ) ; this . updateFromNodeSelection ( tr ) ; dispatch ( tr . scrollIntoView ( ) ) ; return true ; } , } ; } createInputRules ( ) { return [ nodeInputRule ( { regexp : /^(?:---|___\s|\*\*\*\s)$/ , type : this . type , beforeDispatch : ( { tr } ) => { this . updateFromNodeSelection ( tr ) ; } , } ) , ] ; } /**
     * Updates the transaction after a `horizontalRule` has been inserted to make
     * sure the currently selected node isn't a Horizontal Rule.
     *
     * This should only be called for empty selections.
     */ private updateFromNodeSelection ( tr ) { if ( ! isNodeSelection ( tr . selection ) || tr . selection . node . type . name !== this . name ) { return ; } const pos = tr . selection . $from . pos + 1 ; const { insertionNode } = this . options ; if ( ! insertionNode ) { return ; } const type = this . store . schema . nodes [ insertionNode ] ; invariant ( type , { code : ErrorConstant . EXTENSION , message : `'${ insertionNode }' node provided as the insertionNode to the '${ this . constructorName }' does not exist.` , } ) ; const node = type . create ( ) ; tr . insert ( pos , node ) ; tr . setSelection ( TextSelection . create ( tr . doc , pos + 1 ) ) ; } } declare global { namespace Remirror { interface AllExtensions { horizontalRule : HorizontalRuleExtension ; } } }