UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

107 lines (102 loc) 3.59 kB
import { EditorState, Transaction, EditorView, ResolvedPos, Schema } from '../../prosemirror'; import * as commands from '../../commands'; import * as baseListCommand from '../../prosemirror/prosemirror-schema-list'; import { liftFollowingList } from '../../commands/lists'; export const enterKeyCommand = (state: EditorState<any>, dispatch: (tr: Transaction) => void): boolean => { const { selection } = state; if (selection.empty) { const { $from } = selection; const { listItem } = state.schema.nodes; const node = $from.node($from.depth); const wrapper = $from.node($from.depth - 1); if (wrapper.type === listItem) { if (node.textContent.length === 0) { return commands.outdentList()(state, dispatch); } else { return baseListCommand.splitListItem(listItem)(state, dispatch); } } } return false; }; export const toggleList = ( state: EditorState<any>, dispatch: (tr: Transaction) => void, view: EditorView, listType: 'bulletList' | 'orderedList' ): boolean => { const { selection } = state; const { bulletList, orderedList, listItem } = state.schema.nodes; const fromNode = selection.$from.node(selection.$from.depth - 2); const endNode = selection.$to.node(selection.$to.depth - 2); if ((!fromNode || fromNode.type.name !== listType) || (!endNode || endNode.type.name !== listType)) { return commands.toggleList(listType)(state, dispatch, view); } else { let rootListDepth; for (let i = selection.$to.depth - 1; i > 0; i--) { const node = selection.$to.node(i); if (node.type === bulletList || node.type === orderedList) { rootListDepth = i; } if (node.type !== bulletList && node.type !== orderedList && node.type !== listItem) { break; } } let tr = liftFollowingList( state, selection.$to.pos, selection.$to.end(rootListDepth), rootListDepth, state.tr ); tr = liftSelectionList(state, tr); dispatch(tr); return true; } }; /** * The function will list paragraphs in selection out to level 1 below root list. */ function liftSelectionList(state: EditorState<any>, tr: Transaction): Transaction { const { from, to } = state.selection; const { paragraph } = state.schema.nodes; const listCol: any[] = []; tr.doc.nodesBetween(from, to, (node, pos) => { if (node.type === paragraph) { listCol.push({ node, pos }); } }); for (let i = listCol.length - 1; i >= 0; i--) { const paragraph = listCol[i]; const start = tr.doc.resolve(tr.mapping.map(paragraph.pos)); if (start.depth > 0) { let end; if (paragraph.node.textContent && paragraph.node.textContent.length > 0) { end = tr.doc.resolve(tr.mapping.map(paragraph.pos + paragraph.node.textContent.length)); } else { end = tr.doc.resolve(tr.mapping.map(paragraph.pos + 1)); } const range = start.blockRange(end)!; tr.lift(range, listLiftTarget(state.schema, start)); } } return tr; } /** * This will return (depth - 1) for root list parent of a list. */ function listLiftTarget(schema: Schema<any, any>, resPos: ResolvedPos): number { let target = resPos.depth; const { bulletList, orderedList, listItem } = schema.nodes; for (let i = resPos.depth; i > 0; i--) { const node = resPos.node(i); if (node.type === bulletList || node.type === orderedList) { target = i; } if (node.type !== bulletList && node.type !== orderedList && node.type !== listItem) { break; } } return target - 1; }