toggleList.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { wrapInList, liftListItem } from 'prosemirror-schema-list';
  2. import type { Node, NodeType } from 'prosemirror-model';
  3. import type { Transaction, EditorState } from 'prosemirror-state';
  4. import { findParentNode, isList } from '../utils';
  5. type Attr = Record<string, number | string>;
  6. interface TextStyleAttr {
  7. color?: string;
  8. fontsize?: string;
  9. }
  10. export const toggleList = (
  11. listType: NodeType,
  12. itemType: NodeType,
  13. listStyleType: string,
  14. textStyleAttr: TextStyleAttr = {},
  15. ) => {
  16. return (state: EditorState, dispatch: (tr: Transaction) => void) => {
  17. const { schema, selection } = state;
  18. const { $from, $to } = selection;
  19. const range = $from.blockRange($to);
  20. if (!range) return false;
  21. const parentList = findParentNode((node: Node) => isList(node, schema))(selection);
  22. if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
  23. if (parentList.node.type === listType && !listStyleType) {
  24. return liftListItem(itemType)(state, dispatch);
  25. }
  26. if (isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {
  27. const { tr } = state;
  28. const nodeAttrs: Attr = {
  29. ...parentList.node.attrs,
  30. ...textStyleAttr,
  31. };
  32. if (listStyleType) nodeAttrs.listStyleType = listStyleType;
  33. tr.setNodeMarkup(parentList.pos, listType, nodeAttrs);
  34. if (dispatch) dispatch(tr);
  35. return false;
  36. }
  37. }
  38. const nodeAttrs: Attr = {
  39. ...textStyleAttr,
  40. };
  41. if (listStyleType) nodeAttrs.listStyleType = listStyleType;
  42. return wrapInList(listType, nodeAttrs)(state, dispatch);
  43. };
  44. };