UNPKG

3.37 kBJavaScriptView Raw
1import Parchment from 'parchment';
2import Block from '../blots/block';
3import Container from '../blots/container';
4
5
6class 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}
38ListItem.blotName = 'list-item';
39ListItem.tagName = 'LI';
40
41
42class 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 domNode.addEventListener('click', (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
78 format(name, value) {
79 if (this.children.length > 0) {
80 this.children.tail.format(name, value);
81 }
82 }
83
84 formats() {
85 // We don't inherit from FormatBlot
86 return { [this.statics.blotName]: this.statics.formats(this.domNode) };
87 }
88
89 insertBefore(blot, ref) {
90 if (blot instanceof ListItem) {
91 super.insertBefore(blot, ref);
92 } else {
93 let index = ref == null ? this.length() : ref.offset(this);
94 let after = this.split(index);
95 after.parent.insertBefore(blot, after);
96 }
97 }
98
99 optimize(context) {
100 super.optimize(context);
101 let next = this.next;
102 if (next != null && next.prev === this &&
103 next.statics.blotName === this.statics.blotName &&
104 next.domNode.tagName === this.domNode.tagName &&
105 next.domNode.getAttribute('data-checked') === this.domNode.getAttribute('data-checked')) {
106 next.moveChildren(this);
107 next.remove();
108 }
109 }
110
111 replace(target) {
112 if (target.statics.blotName !== this.statics.blotName) {
113 let item = Parchment.create(this.statics.defaultChild);
114 target.moveChildren(item);
115 this.appendChild(item);
116 }
117 super.replace(target);
118 }
119}
120List.blotName = 'list';
121List.scope = Parchment.Scope.BLOCK_BLOT;
122List.tagName = ['OL', 'UL'];
123List.defaultChild = 'list-item';
124List.allowedChildren = [ListItem];
125
126
127export { ListItem, List as default };