File size: 1,660 Bytes
f56a29b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import { wrapInList, liftListItem } from 'prosemirror-schema-list';
import type { Node, NodeType } from 'prosemirror-model';
import type { Transaction, EditorState } from 'prosemirror-state';
import { findParentNode, isList } from '../utils';

type Attr = Record<string, number | string>;

interface TextStyleAttr {
  color?: string;
  fontsize?: string;
}

export const toggleList = (
  listType: NodeType,
  itemType: NodeType,
  listStyleType: string,
  textStyleAttr: TextStyleAttr = {},
) => {
  return (state: EditorState, dispatch: (tr: Transaction) => void) => {
    const { schema, selection } = state;
    const { $from, $to } = selection;
    const range = $from.blockRange($to);

    if (!range) return false;

    const parentList = findParentNode((node: Node) => isList(node, schema))(selection);

    if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
      if (parentList.node.type === listType && !listStyleType) {
        return liftListItem(itemType)(state, dispatch);
      }

      if (isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {
        const { tr } = state;

        const nodeAttrs: Attr = {
          ...parentList.node.attrs,
          ...textStyleAttr,
        };
        if (listStyleType) nodeAttrs.listStyleType = listStyleType;

        tr.setNodeMarkup(parentList.pos, listType, nodeAttrs);

        if (dispatch) dispatch(tr);

        return false;
      }
    }

    const nodeAttrs: Attr = {
      ...textStyleAttr,
    };
    if (listStyleType) nodeAttrs.listStyleType = listStyleType;

    return wrapInList(listType, nodeAttrs)(state, dispatch);
  };
};