Created
March 24, 2021 09:23
-
-
Save paxapy/c868759e09d89ed32e39bb0afc9ab24a to your computer and use it in GitHub Desktop.
prosemirror list toggle set.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type PredicateCommand = (state: EditorState, dispatch?: (tr: Transaction) => void) => boolean; | |
/** | |
* Creates a new EditorCommand that wraps/unwraps the selection in a given list itemType. | |
* To be used by list and list item types. | |
*/ | |
export function toggleListNode(nodeType: NodeType): EditorCommand { | |
return { | |
enable: () => true, | |
active: (state) => isNodeActive(state, nodeType), | |
run: (state, dispatch) => { | |
const itemType = getListItemType(nodeType, state); | |
if (isNodeActive(state, nodeType)) { | |
return liftListItem(itemType)(state, dispatch); | |
} else if (listNodeActive(state)) { | |
const predicate = chainTransactions(liftListItem(itemType), wrapInList(nodeType)); | |
return predicate(state, dispatch); | |
} else { | |
return wrapInList(nodeType)(state, dispatch); | |
} | |
}, | |
}; | |
} | |
/** | |
* Returns list item type by list node type and state (used to get schema). | |
*/ | |
function getListItemType(nodeType: NodeType, state: EditorState): NodeType { | |
const nodes = state.schema.nodes; | |
const itemTypeMap: { [key: string]: NodeType } = { | |
bullet_list: nodes.list_item, | |
ordered_list: nodes.list_item, | |
check_list: nodes.check_list_item, | |
}; | |
return itemTypeMap[nodeType.name]; | |
} | |
/** | |
* Chain passed commands with consenquent state applyment. | |
*/ | |
function chainTransactions(...commands: PredicateCommand[]): PredicateCommand { | |
return (state, dispatch): boolean => { | |
const dispatcher = (tr: Transaction): void => { | |
state = state.apply(tr); | |
dispatch(tr); | |
}; | |
const last = commands.pop(); | |
const reduced = commands.reduce((result, command) => { | |
return result || command(state, dispatcher); | |
}, false); | |
return reduced && last !== undefined && last(state, dispatch); | |
}; | |
} | |
/** | |
* Checks if the the active node is one of the list nodes. | |
*/ | |
export function listNodeActive(state: EditorState): boolean { | |
const listTypes = ['bullet_list', 'ordered_list']; | |
const predicate = hasParentNode((node) => listTypes.includes(node.type.name)); | |
return predicate(state.selection); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment