Skip to content

Commit

Permalink
implement code-block using container
Browse files Browse the repository at this point in the history
  • Loading branch information
jhchen committed Mar 20, 2018
1 parent 7f0021b commit ad537d0
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 169 deletions.
7 changes: 3 additions & 4 deletions assets/base.styl
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,17 @@ colorItemsPerRow = 7
margin-bottom: 5px
margin-top: 5px
padding-left: 16px
code, pre
code, .ql-code-block-container
background-color: #f0f0f0
border-radius: 3px
pre
white-space: pre-wrap
.ql-code-block-container
margin-bottom: 5px
margin-top: 5px
padding: 5px 10px
code
font-size: 85%
padding: 2px 4px
pre.ql-syntax
.ql-code-block-container.ql-syntax
background-color: #23241f
color: #f8f8f2;
overflow: visible
Expand Down
3 changes: 3 additions & 0 deletions assets/core.styl
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ resets(arr)
margin-right: -1*LIST_STYLE_OUTER_WIDTH
text-align: left

.ql-code-block-container
font-family: monospace

.ql-video
display: block
max-width: 100%
Expand Down
19 changes: 1 addition & 18 deletions blots/scroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import Parchment from 'parchment';
import Emitter from '../core/emitter';
import Block, { BlockEmbed } from './block';
import Break from './break';
import CodeBlock from '../formats/code';
import Container from './container';

function isLine(blot) {
Expand Down Expand Up @@ -35,30 +34,14 @@ class Scroll extends Parchment.Scroll {
}

deleteAt(index, length) {
const [firstLine, offset] = this.line(index);
let first = firstLine;
const [first, offset] = this.line(index);
const [last] = this.line(index + length);
super.deleteAt(index, length);
if (last != null && first !== last && offset > 0) {
if (first instanceof BlockEmbed || last instanceof BlockEmbed) {
this.optimize();
return;
}
if (first instanceof CodeBlock) {
const newlineIndex = first.newlineIndex(first.length(), true);
if (newlineIndex > -1) {
first = first.split(newlineIndex + 1);
if (first === last) {
this.optimize();
return;
}
}
} else if (last instanceof CodeBlock) {
const newlineIndex = last.newlineIndex(0);
if (newlineIndex > -1) {
last.split(newlineIndex + 1);
}
}
const ref =
last.children.head instanceof Break ? null : last.children.head;
first.moveChildren(last, ref);
Expand Down
21 changes: 3 additions & 18 deletions core/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,8 @@ class Editor {
Object.keys(formats).forEach(format => {
if (this.scroll.whitelist != null && !this.scroll.whitelist[format])
return;
const lines = this.scroll.lines(index, Math.max(length, 1));
let lengthRemaining = length;
lines.forEach(line => {
const lineLength = line.length();
if (!(line instanceof CodeBlock)) {
line.format(format, formats[format]);
} else {
const codeIndex = index - line.offset(this.scroll);
const codeLength =
line.newlineIndex(codeIndex + lengthRemaining) - codeIndex + 1;
line.formatAt(codeIndex, codeLength, format, formats[format]);
}
lengthRemaining -= lineLength;
this.scroll.lines(index, Math.max(length, 1)).forEach(line => {
line.format(format, formats[format]);
});
});
this.scroll.optimize();
Expand Down Expand Up @@ -182,11 +171,7 @@ class Editor {
let suffixLength = 0;
let suffix = new Delta();
if (line != null) {
if (!(line instanceof CodeBlock)) {
suffixLength = line.length() - offset;
} else {
suffixLength = line.newlineIndex(offset) - offset + 1;
}
suffixLength = line.length() - offset;
suffix = line
.delta()
.slice(offset, offset + suffixLength - 1)
Expand Down
126 changes: 14 additions & 112 deletions formats/code.js
Original file line number Diff line number Diff line change
@@ -1,127 +1,29 @@
import Delta from 'quill-delta';
import Parchment from 'parchment';
import Block from '../blots/block';
import Inline from '../blots/inline';
import TextBlot from '../blots/text';
import Container from '../blots/container';

class Code extends Inline {}
Code.blotName = 'code';
Code.tagName = 'CODE';

class CodeBlock extends Block {
class CodeBlock extends Block {}
CodeBlock.blotName = 'code-block';
CodeBlock.className = 'ql-code-block';
CodeBlock.tagName = 'DIV';

class CodeBlockContainer extends Container {
static create(value) {
const domNode = super.create(value);
domNode.setAttribute('spellcheck', false);
return domNode;
}

static formats() {
return true;
}

delta() {
let text = this.domNode.textContent;
if (text.endsWith('\n')) {
// Should always be true
text = text.slice(0, -1);
}
return text.split('\n').reduce((delta, frag) => {
return delta.insert(frag).insert('\n', this.formats());
}, new Delta());
}

format(name, value) {
if (name === this.statics.blotName && value) return;
const [text] = this.descendant(TextBlot, this.length() - 1);
if (text != null) {
text.deleteAt(text.length() - 1, 1);
}
super.format(name, value);
}

formatAt(index, length, name, value) {
if (length === 0) return;
if (
Parchment.query(name, Parchment.Scope.BLOCK) == null ||
(name === this.statics.blotName &&
value === this.statics.formats(this.domNode))
) {
return;
}
const nextNewline = this.newlineIndex(index);
if (nextNewline < 0 || nextNewline >= index + length) return;
const prevNewline = this.newlineIndex(index, true) + 1;
const isolateLength = nextNewline - prevNewline + 1;
const blot = this.isolate(prevNewline, isolateLength);
const { next } = blot;
blot.format(name, value);
if (next instanceof CodeBlock) {
next.formatAt(
0,
index - prevNewline + length - isolateLength,
name,
value,
);
}
}

insertAt(index, value, def) {
if (def != null) return;
const [text, offset] = this.descendant(TextBlot, index);
text.insertAt(offset, value);
}

length() {
const { length } = this.domNode.textContent;
if (!this.domNode.textContent.endsWith('\n')) {
return length + 1;
}
return length;
}

newlineIndex(searchIndex, reverse = false) {
if (!reverse) {
const offset = this.domNode.textContent.slice(searchIndex).indexOf('\n');
return offset > -1 ? searchIndex + offset : -1;
}
return this.domNode.textContent.slice(0, searchIndex).lastIndexOf('\n');
}

optimize(context) {
if (!this.domNode.textContent.endsWith('\n')) {
this.appendChild(Parchment.create('text', '\n'));
}
super.optimize(context);
const { next } = this;
if (
next != null &&
next.prev === this &&
next.statics.blotName === this.statics.blotName &&
this.statics.formats(this.domNode) === next.statics.formats(next.domNode)
) {
next.optimize(context);
next.moveChildren(this);
next.remove();
}
}

// TODO no longer a thing
replace(target) {
super.replace(target);
[].slice.call(this.domNode.querySelectorAll('*')).forEach(node => {
const blot = Parchment.find(node);
if (blot == null) {
node.parentNode.removeChild(node);
} else if (blot instanceof Parchment.Embed) {
blot.remove();
} else {
blot.unwrap();
}
});
}
}
CodeBlock.blotName = 'code-block';
CodeBlock.tagName = 'PRE';
CodeBlockContainer.blotName = 'code-block-container';
CodeBlockContainer.className = 'ql-code-block-container';
CodeBlockContainer.tagName = 'DIV';

CodeBlockContainer.allowedChildren = [CodeBlock];
CodeBlock.requiredContainer = CodeBlockContainer;
CodeBlock.TAB = ' ';

export { Code, CodeBlock as default };
export { Code, CodeBlockContainer, CodeBlock as default };
5 changes: 5 additions & 0 deletions modules/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const CLIPBOARD_CONFIG = [
[Node.ELEMENT_NODE, matchStyles],
['li', matchIndent],
['ol, ul', matchList],
['pre', matchCodeBlock],
['tr', matchTable],
['b', matchAlias.bind(matchAlias, 'bold')],
['i', matchAlias.bind(matchAlias, 'italic')],
Expand Down Expand Up @@ -299,6 +300,10 @@ function matchBreak(node, delta) {
return delta;
}

function matchCodeBlock(node, delta) {
return applyFormat(delta, 'code-block', true);
}

function matchIgnore() {
return new Delta();
}
Expand Down
20 changes: 4 additions & 16 deletions modules/keyboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -496,36 +496,24 @@ function makeCodeBlockHandler(indent) {
format: { 'code-block': true },
handler(range) {
const CodeBlock = Parchment.query('code-block');
const lines = this.quill.getLines(range);
let { index, length } = range;
const [block, blockOffset] = this.quill.scroll.descendant(
CodeBlock,
index,
);
if (block == null) return;
const scrollIndex = this.quill.getIndex(block);
const start = block.newlineIndex(blockOffset, true) + 1;
const end = block.newlineIndex(scrollIndex + blockOffset + length);
const lines = block.domNode.textContent.slice(start, end).split('\n');
let offset = 0;
lines.forEach((line, i) => {
if (indent) {
block.insertAt(start + offset, CodeBlock.TAB);
offset += CodeBlock.TAB.length;
line.insertAt(0, CodeBlock.TAB);
if (i === 0) {
index += CodeBlock.TAB.length;
} else {
length += CodeBlock.TAB.length;
}
} else if (line.startsWith(CodeBlock.TAB)) {
block.deleteAt(start + offset, CodeBlock.TAB.length);
offset -= CodeBlock.TAB.length;
} else if (line.domNode.textContent.startsWith(CodeBlock.TAB)) {
line.deleteAt(0, CodeBlock.TAB.length);
if (i === 0) {
index -= CodeBlock.TAB.length;
} else {
length -= CodeBlock.TAB.length;
}
}
offset += line.length + 1;
});
this.quill.update(Quill.sources.USER);
this.quill.setSelection(index, length, Quill.sources.SILENT);
Expand Down
6 changes: 5 additions & 1 deletion quill.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import Formula from './formats/formula';
import Image from './formats/image';
import Video from './formats/video';

import CodeBlock, { Code as InlineCode } from './formats/code';
import CodeBlock, {
CodeBlockContainer,
Code as InlineCode,
} from './formats/code';

import Syntax from './modules/syntax';
import Toolbar from './modules/toolbar';
Expand Down Expand Up @@ -71,6 +74,7 @@ Quill.register(

Quill.register(
{
'blots/code-block-container': CodeBlockContainer,
'blots/list-container': ListContainer,
'blots/table-container': TableContainer,
'blots/table-body': TableBody,
Expand Down

0 comments on commit ad537d0

Please sign in to comment.