import { MarkType , NodeType , Schema } from 'prosemirror-model' ; import { Plugin } from 'prosemirror-state' ; import { keymap } from 'prosemirror-keymap' ; import { toggleMark , baseKeymap , chainCommands , exitCode } from 'prosemirror-commands' ; import { splitListItem , liftListItem , sinkListItem } from 'prosemirror-schema-list' ; import { history , undo , redo } from 'prosemirror-history' ; import { inputRules , wrappingInputRule , textblockTypeInputRule , smartQuotes , emDash , ellipsis , InputRule } from 'prosemirror-inputrules' ; import { markInputRule } from 'ngx-editor/helpers' ; interface Options { history : boolean ; keyboardShortcuts : boolean ; inputRules : boolean ; } interface ShortcutOptions { history : boolean ; } const isMacOs = typeof navigator !== 'undefined' ? /Mac/ . test ( navigator . platform ) : false ; const blockQuoteRule = ( nodeType ) : InputRule => { return wrappingInputRule ( /^\s*>\s$/ , nodeType ) ; } ; const orderedListRule = ( nodeType ) : InputRule => { return wrappingInputRule ( /^(\d+)\.\s$/ , nodeType , match => ( { order : + match [ 1 ] } ) , ( match , node ) => node . childCount + node . attrs [ 'order' ] === + match [ 1 ] ) ; } ; const bulletListRule = ( nodeType ) : InputRule => { return wrappingInputRule ( /^\s*([-+*])\s$/ , nodeType ) ; } ; const codeBlockRule = ( nodeType ) : InputRule => { return textblockTypeInputRule ( /^```$/ , nodeType ) ; } ; const headingRule = ( nodeType , maxLevel ) : InputRule => { return textblockTypeInputRule ( new RegExp ( '^(#{1,' + maxLevel + '})\\s$' ) , nodeType , ( match ) => ( { level : match [ 1 ] . length } ) ) ; } ; const boldRule = ( markType ) : InputRule => { return markInputRule ( /(?:^|\s)((?:\*\*|__)((?:[^*_]+))(?:\*\*|__))$/ , markType ) ; } ; const emRule = ( markType ) : InputRule => { return markInputRule ( /(?:^|\s)((?:\*|_)((?:[^*_]+))(?:\*|_))$/ , markType ) ; } ; const buildInputRules = ( schema ) : Plugin => { const rules = smartQuotes . concat ( ellipsis , emDash ) ; rules . push ( boldRule ( schema . marks [ 'strong' ] ) ) ; rules . push ( emRule ( schema . marks [ 'em' ] ) ) ; rules . push ( blockQuoteRule ( schema . nodes [ 'blockquote' ] ) ) ; rules . push ( orderedListRule ( schema . nodes [ 'ordered_list' ] ) ) ; rules . push ( bulletListRule ( schema . nodes [ 'bullet_list' ] ) ) ; rules . push ( codeBlockRule ( schema . nodes [ 'code_block' ] ) ) ; rules . push ( headingRule ( schema . nodes [ 'heading' ] , 6 ) ) ; return inputRules ( { rules } ) ; } ; const getKeyboardShortcuts = ( schema , options ) => { const historyKeyMap = { } ; historyKeyMap [ 'Mod-z' ] = undo ; if ( isMacOs ) { historyKeyMap [ 'Shift-Mod-z' ] = redo ; } else { historyKeyMap [ 'Mod-y' ] = redo ; } const plugins = [ keymap ( { 'Mod-b' : toggleMark ( schema . marks [ 'strong' ] ) , 'Mod-i' : toggleMark ( schema . marks [ 'em' ] ) , 'Mod-u' : toggleMark ( schema . marks [ 'u' ] ) , 'Mod-`' : toggleMark ( schema . marks [ 'code' ] ) , } ) , keymap ( { Enter : splitListItem ( schema . nodes [ 'list_item' ] ) , 'Shift-Enter' : chainCommands ( exitCode , ( state , dispatch ) => { const tr = state . tr ; const br = schema . nodes [ 'hard_break' ] ; dispatch ( tr . replaceSelectionWith ( br . create ( ) ) . scrollIntoView ( ) ) ; return true ; } ) , 'Mod-[' : liftListItem ( schema . nodes [ 'list_item' ] ) , 'Mod-]' : sinkListItem ( schema . nodes [ 'list_item' ] ) , Tab : sinkListItem ( schema . nodes [ 'list_item' ] ) } ) , keymap ( baseKeymap ) ] ; if ( options . history ) { plugins . push ( keymap ( historyKeyMap ) ) ; } return plugins ; } ; const getDefaultPlugins = ( schema , options ) : Plugin [ ] => { const plugins = [ ] ; if ( options . keyboardShortcuts ) { plugins . push ( ... getKeyboardShortcuts ( schema , { history : options . history } ) ) ; } if ( options . history ) { plugins . push ( history ( ) ) ; } if ( options . inputRules ) { plugins . push ( buildInputRules ( schema ) ) ; } return plugins ; } ; export default getDefaultPlugins ;