131 lines
3.4 KiB
JavaScript
131 lines
3.4 KiB
JavaScript
|
import Parchment from 'parchment';
|
||
|
import Block from '../blots/block';
|
||
|
import Container from '../blots/container';
|
||
|
|
||
|
|
||
|
class ListItem extends Block {
|
||
|
static formats(domNode) {
|
||
|
return domNode.tagName === this.tagName ? undefined : super.formats(domNode);
|
||
|
}
|
||
|
|
||
|
format(name, value) {
|
||
|
if (name === List.blotName && !value) {
|
||
|
this.replaceWith(Parchment.create(this.statics.scope));
|
||
|
} else {
|
||
|
super.format(name, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
remove() {
|
||
|
if (this.prev == null && this.next == null) {
|
||
|
this.parent.remove();
|
||
|
} else {
|
||
|
super.remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
replaceWith(name, value) {
|
||
|
this.parent.isolate(this.offset(this.parent), this.length());
|
||
|
if (name === this.parent.statics.blotName) {
|
||
|
this.parent.replaceWith(name, value);
|
||
|
return this;
|
||
|
} else {
|
||
|
this.parent.unwrap();
|
||
|
return super.replaceWith(name, value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
ListItem.blotName = 'list-item';
|
||
|
ListItem.tagName = 'LI';
|
||
|
|
||
|
|
||
|
class List extends Container {
|
||
|
static create(value) {
|
||
|
let tagName = value === 'ordered' ? 'OL' : 'UL';
|
||
|
let node = super.create(tagName);
|
||
|
if (value === 'checked' || value === 'unchecked') {
|
||
|
node.setAttribute('data-checked', value === 'checked');
|
||
|
}
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
static formats(domNode) {
|
||
|
if (domNode.tagName === 'OL') return 'ordered';
|
||
|
if (domNode.tagName === 'UL') {
|
||
|
if (domNode.hasAttribute('data-checked')) {
|
||
|
return domNode.getAttribute('data-checked') === 'true' ? 'checked' : 'unchecked';
|
||
|
} else {
|
||
|
return 'bullet';
|
||
|
}
|
||
|
}
|
||
|
return undefined;
|
||
|
}
|
||
|
|
||
|
constructor(domNode) {
|
||
|
super(domNode);
|
||
|
const listEventHandler = (e) => {
|
||
|
if (e.target.parentNode !== domNode) return;
|
||
|
let format = this.statics.formats(domNode);
|
||
|
let blot = Parchment.find(e.target);
|
||
|
if (format === 'checked') {
|
||
|
blot.format('list', 'unchecked');
|
||
|
} else if(format === 'unchecked') {
|
||
|
blot.format('list', 'checked');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
domNode.addEventListener('touchstart', listEventHandler);
|
||
|
domNode.addEventListener('mousedown', listEventHandler);
|
||
|
}
|
||
|
|
||
|
format(name, value) {
|
||
|
if (this.children.length > 0) {
|
||
|
this.children.tail.format(name, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
formats() {
|
||
|
// We don't inherit from FormatBlot
|
||
|
return { [this.statics.blotName]: this.statics.formats(this.domNode) };
|
||
|
}
|
||
|
|
||
|
insertBefore(blot, ref) {
|
||
|
if (blot instanceof ListItem) {
|
||
|
super.insertBefore(blot, ref);
|
||
|
} else {
|
||
|
let index = ref == null ? this.length() : ref.offset(this);
|
||
|
let after = this.split(index);
|
||
|
after.parent.insertBefore(blot, after);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
optimize(context) {
|
||
|
super.optimize(context);
|
||
|
let next = this.next;
|
||
|
if (next != null && next.prev === this &&
|
||
|
next.statics.blotName === this.statics.blotName &&
|
||
|
next.domNode.tagName === this.domNode.tagName &&
|
||
|
next.domNode.getAttribute('data-checked') === this.domNode.getAttribute('data-checked')) {
|
||
|
next.moveChildren(this);
|
||
|
next.remove();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
replace(target) {
|
||
|
if (target.statics.blotName !== this.statics.blotName) {
|
||
|
let item = Parchment.create(this.statics.defaultChild);
|
||
|
target.moveChildren(item);
|
||
|
this.appendChild(item);
|
||
|
}
|
||
|
super.replace(target);
|
||
|
}
|
||
|
}
|
||
|
List.blotName = 'list';
|
||
|
List.scope = Parchment.Scope.BLOCK_BLOT;
|
||
|
List.tagName = ['OL', 'UL'];
|
||
|
List.defaultChild = 'list-item';
|
||
|
List.allowedChildren = [ListItem];
|
||
|
|
||
|
|
||
|
export { ListItem, List as default };
|