UNPKG

3.34 kBJavaScriptView Raw
1import Delta from 'quill-delta';
2import Parchment from 'parchment';
3import Block from '../blots/block';
4import Inline from '../blots/inline';
5import TextBlot from '../blots/text';
6
7
8class Code extends Inline {}
9Code.blotName = 'code';
10Code.tagName = 'CODE';
11
12
13class CodeBlock extends Block {
14 static create(value) {
15 let domNode = super.create(value);
16 domNode.setAttribute('spellcheck', false);
17 return domNode;
18 }
19
20 static formats() {
21 return true;
22 }
23
24 delta() {
25 let text = this.domNode.textContent;
26 if (text.endsWith('\n')) { // Should always be true
27 text = text.slice(0, -1);
28 }
29 return text.split('\n').reduce((delta, frag) => {
30 return delta.insert(frag).insert('\n', this.formats());
31 }, new Delta());
32 }
33
34 format(name, value) {
35 if (name === this.statics.blotName && value) return;
36 let [text, ] = this.descendant(TextBlot, this.length() - 1);
37 if (text != null) {
38 text.deleteAt(text.length() - 1, 1);
39 }
40 super.format(name, value);
41 }
42
43 formatAt(index, length, name, value) {
44 if (length === 0) return;
45 if (Parchment.query(name, Parchment.Scope.BLOCK) == null ||
46 (name === this.statics.blotName && value === this.statics.formats(this.domNode))) {
47 return;
48 }
49 let nextNewline = this.newlineIndex(index);
50 if (nextNewline < 0 || nextNewline >= index + length) return;
51 let prevNewline = this.newlineIndex(index, true) + 1;
52 let isolateLength = nextNewline - prevNewline + 1;
53 let blot = this.isolate(prevNewline, isolateLength);
54 let next = blot.next;
55 blot.format(name, value);
56 if (next instanceof CodeBlock) {
57 next.formatAt(0, index - prevNewline + length - isolateLength, name, value);
58 }
59 }
60
61 insertAt(index, value, def) {
62 if (def != null) return;
63 let [text, offset] = this.descendant(TextBlot, index);
64 text.insertAt(offset, value);
65 }
66
67 length() {
68 let length = this.domNode.textContent.length;
69 if (!this.domNode.textContent.endsWith('\n')) {
70 return length + 1;
71 }
72 return length;
73 }
74
75 newlineIndex(searchIndex, reverse = false) {
76 if (!reverse) {
77 let offset = this.domNode.textContent.slice(searchIndex).indexOf('\n');
78 return offset > -1 ? searchIndex + offset : -1;
79 } else {
80 return this.domNode.textContent.slice(0, searchIndex).lastIndexOf('\n');
81 }
82 }
83
84 optimize(context) {
85 if (!this.domNode.textContent.endsWith('\n')) {
86 this.appendChild(Parchment.create('text', '\n'));
87 }
88 super.optimize(context);
89 let next = this.next;
90 if (next != null && next.prev === this &&
91 next.statics.blotName === this.statics.blotName &&
92 this.statics.formats(this.domNode) === next.statics.formats(next.domNode)) {
93 next.optimize(context);
94 next.moveChildren(this);
95 next.remove();
96 }
97 }
98
99 replace(target) {
100 super.replace(target);
101 [].slice.call(this.domNode.querySelectorAll('*')).forEach(function(node) {
102 let blot = Parchment.find(node);
103 if (blot == null) {
104 node.parentNode.removeChild(node);
105 } else if (blot instanceof Parchment.Embed) {
106 blot.remove();
107 } else {
108 blot.unwrap();
109 }
110 });
111 }
112}
113CodeBlock.blotName = 'code-block';
114CodeBlock.tagName = 'PRE';
115CodeBlock.TAB = ' ';
116
117
118export { Code, CodeBlock as default };