1 | import Parchment from 'parchment';
|
2 | import Block from '../blots/block';
|
3 | import Container from '../blots/container';
|
4 |
|
5 |
|
6 | class ListItem extends Block {
|
7 | static formats(domNode) {
|
8 | return domNode.tagName === this.tagName ? undefined : super.formats(domNode);
|
9 | }
|
10 |
|
11 | format(name, value) {
|
12 | if (name === List.blotName && !value) {
|
13 | this.replaceWith(Parchment.create(this.statics.scope));
|
14 | } else {
|
15 | super.format(name, value);
|
16 | }
|
17 | }
|
18 |
|
19 | remove() {
|
20 | if (this.prev == null && this.next == null) {
|
21 | this.parent.remove();
|
22 | } else {
|
23 | super.remove();
|
24 | }
|
25 | }
|
26 |
|
27 | replaceWith(name, value) {
|
28 | this.parent.isolate(this.offset(this.parent), this.length());
|
29 | if (name === this.parent.statics.blotName) {
|
30 | this.parent.replaceWith(name, value);
|
31 | return this;
|
32 | } else {
|
33 | this.parent.unwrap();
|
34 | return super.replaceWith(name, value);
|
35 | }
|
36 | }
|
37 | }
|
38 | ListItem.blotName = 'list-item';
|
39 | ListItem.tagName = 'LI';
|
40 |
|
41 |
|
42 | class List extends Container {
|
43 | static create(value) {
|
44 | let tagName = value === 'ordered' ? 'OL' : 'UL';
|
45 | let node = super.create(tagName);
|
46 | if (value === 'checked' || value === 'unchecked') {
|
47 | node.setAttribute('data-checked', value === 'checked');
|
48 | }
|
49 | return node;
|
50 | }
|
51 |
|
52 | static formats(domNode) {
|
53 | if (domNode.tagName === 'OL') return 'ordered';
|
54 | if (domNode.tagName === 'UL') {
|
55 | if (domNode.hasAttribute('data-checked')) {
|
56 | return domNode.getAttribute('data-checked') === 'true' ? 'checked' : 'unchecked';
|
57 | } else {
|
58 | return 'bullet';
|
59 | }
|
60 | }
|
61 | return undefined;
|
62 | }
|
63 |
|
64 | constructor(domNode) {
|
65 | super(domNode);
|
66 | const listEventHandler = (e) => {
|
67 | if (e.target.parentNode !== domNode) return;
|
68 | let format = this.statics.formats(domNode);
|
69 | let blot = Parchment.find(e.target);
|
70 | if (format === 'checked') {
|
71 | blot.format('list', 'unchecked');
|
72 | } else if(format === 'unchecked') {
|
73 | blot.format('list', 'checked');
|
74 | }
|
75 | }
|
76 |
|
77 | domNode.addEventListener('touchstart', listEventHandler);
|
78 | domNode.addEventListener('mousedown', listEventHandler);
|
79 | }
|
80 |
|
81 | format(name, value) {
|
82 | if (this.children.length > 0) {
|
83 | this.children.tail.format(name, value);
|
84 | }
|
85 | }
|
86 |
|
87 | formats() {
|
88 |
|
89 | return { [this.statics.blotName]: this.statics.formats(this.domNode) };
|
90 | }
|
91 |
|
92 | insertBefore(blot, ref) {
|
93 | if (blot instanceof ListItem) {
|
94 | super.insertBefore(blot, ref);
|
95 | } else {
|
96 | let index = ref == null ? this.length() : ref.offset(this);
|
97 | let after = this.split(index);
|
98 | after.parent.insertBefore(blot, after);
|
99 | }
|
100 | }
|
101 |
|
102 | optimize(context) {
|
103 | super.optimize(context);
|
104 | let next = this.next;
|
105 | if (next != null && next.prev === this &&
|
106 | next.statics.blotName === this.statics.blotName &&
|
107 | next.domNode.tagName === this.domNode.tagName &&
|
108 | next.domNode.getAttribute('data-checked') === this.domNode.getAttribute('data-checked')) {
|
109 | next.moveChildren(this);
|
110 | next.remove();
|
111 | }
|
112 | }
|
113 |
|
114 | replace(target) {
|
115 | if (target.statics.blotName !== this.statics.blotName) {
|
116 | let item = Parchment.create(this.statics.defaultChild);
|
117 | target.moveChildren(item);
|
118 | this.appendChild(item);
|
119 | }
|
120 | super.replace(target);
|
121 | }
|
122 | }
|
123 | List.blotName = 'list';
|
124 | List.scope = Parchment.Scope.BLOCK_BLOT;
|
125 | List.tagName = ['OL', 'UL'];
|
126 | List.defaultChild = 'list-item';
|
127 | List.allowedChildren = [ListItem];
|
128 |
|
129 |
|
130 | export { ListItem, List as default };
|