diff --git a/blots/block.js b/blots/block.js
index 54be6efcf9..5fad9ce8ef 100644
--- a/blots/block.js
+++ b/blots/block.js
@@ -1,10 +1,11 @@
import extend from 'extend';
import Delta from 'quill-delta';
-import Parchment, {
+import {
AttributorStore,
BlockBlot,
EmbedBlot,
LeafBlot,
+ Scope,
} from 'parchment';
import Break from './break';
import Inline from './inline';
@@ -13,8 +14,8 @@ import TextBlot from './text';
const NEWLINE_LENGTH = 1;
class Block extends BlockBlot {
- constructor(domNode) {
- super(domNode);
+ constructor(scroll, domNode) {
+ super(scroll, domNode);
this.cache = {};
}
@@ -39,7 +40,7 @@ class Block extends BlockBlot {
formatAt(index, length, name, value) {
if (length <= 0) return;
- if (Parchment.query(name, Parchment.Scope.BLOCK)) {
+ if (this.scroll.query(name, Scope.BLOCK)) {
if (index + length === this.length()) {
this.format(name, value);
}
@@ -147,7 +148,7 @@ class BlockEmbed extends EmbedBlot {
}
format(name, value) {
- const attribute = Parchment.query(name, Parchment.Scope.BLOCK_ATTRIBUTE);
+ const attribute = this.scroll.query(name, Scope.BLOCK_ATTRIBUTE);
if (attribute != null) {
this.attributes.attribute(attribute, value);
}
@@ -159,7 +160,7 @@ class BlockEmbed extends EmbedBlot {
insertAt(index, value, def) {
if (typeof value === 'string' && value.endsWith('\n')) {
- const block = Parchment.create(Block.blotName);
+ const block = this.scroll.create(Block.blotName);
this.parent.insertBefore(block, index === 0 ? this : this.next);
block.insertAt(0, value.slice(0, -1));
} else {
@@ -167,7 +168,7 @@ class BlockEmbed extends EmbedBlot {
}
}
}
-BlockEmbed.scope = Parchment.Scope.BLOCK_BLOT;
+BlockEmbed.scope = Scope.BLOCK_BLOT;
// It is important for cursor behavior BlockEmbeds use tags that are block level elements
function bubbleFormats(blot, formats = {}) {
diff --git a/blots/cursor.js b/blots/cursor.js
index e992c7bfa9..3f9524e925 100644
--- a/blots/cursor.js
+++ b/blots/cursor.js
@@ -1,4 +1,4 @@
-import Parchment, { EmbedBlot } from 'parchment';
+import { EmbedBlot, Scope } from 'parchment';
import TextBlot from './text';
class Cursor extends EmbedBlot {
@@ -6,8 +6,8 @@ class Cursor extends EmbedBlot {
return undefined;
}
- constructor(domNode, selection) {
- super(domNode);
+ constructor(scroll, domNode, selection) {
+ super(scroll, domNode);
this.selection = selection;
this.textNode = document.createTextNode(Cursor.CONTENTS);
this.domNode.appendChild(this.textNode);
@@ -26,10 +26,7 @@ class Cursor extends EmbedBlot {
}
let target = this;
let index = 0;
- while (
- target != null &&
- target.statics.scope !== Parchment.Scope.BLOCK_BLOT
- ) {
+ while (target != null && target.statics.scope !== Scope.BLOCK_BLOT) {
index += target.offset(target.parent);
target = target.parent;
}
@@ -94,7 +91,7 @@ class Cursor extends EmbedBlot {
this.textNode.data = Cursor.CONTENTS;
} else {
this.textNode.data = text;
- this.parent.insertBefore(Parchment.create(this.textNode), this);
+ this.parent.insertBefore(this.scroll.create(this.textNode), this);
this.textNode = document.createTextNode(Cursor.CONTENTS);
this.domNode.appendChild(this.textNode);
}
diff --git a/blots/embed.js b/blots/embed.js
index 5b5ecb0c27..4d66120ba1 100644
--- a/blots/embed.js
+++ b/blots/embed.js
@@ -1,11 +1,11 @@
-import Parchment, { EmbedBlot } from 'parchment';
+import { EmbedBlot } from 'parchment';
import TextBlot from './text';
const GUARD_TEXT = '\uFEFF';
class Embed extends EmbedBlot {
- constructor(node) {
- super(node);
+ constructor(scroll, node) {
+ super(scroll, node);
this.contentNode = document.createElement('span');
this.contentNode.setAttribute('contenteditable', false);
Array.from(this.domNode.childNodes).forEach(childNode => {
@@ -38,7 +38,7 @@ class Embed extends EmbedBlot {
};
} else {
textNode = document.createTextNode(text);
- this.parent.insertBefore(Parchment.create(textNode), this);
+ this.parent.insertBefore(this.scroll.create(textNode), this);
range = {
startNode: textNode,
startOffset: text.length,
@@ -53,7 +53,7 @@ class Embed extends EmbedBlot {
};
} else {
textNode = document.createTextNode(text);
- this.parent.insertBefore(Parchment.create(textNode), this.next);
+ this.parent.insertBefore(this.scroll.create(textNode), this.next);
range = {
startNode: textNode,
startOffset: text.length,
diff --git a/blots/inline.js b/blots/inline.js
index 446a904761..cad61ac6d6 100644
--- a/blots/inline.js
+++ b/blots/inline.js
@@ -1,4 +1,4 @@
-import Parchment, { EmbedBlot, InlineBlot } from 'parchment';
+import { EmbedBlot, InlineBlot, Scope } from 'parchment';
import Break from './break';
import Text from './text';
@@ -19,7 +19,7 @@ class Inline extends InlineBlot {
formatAt(index, length, name, value) {
if (
Inline.compare(this.statics.blotName, name) < 0 &&
- Parchment.query(name, Parchment.Scope.BLOT)
+ this.scroll.query(name, Scope.BLOT)
) {
const blot = this.isolate(index, length);
if (value) {
diff --git a/blots/scroll.js b/blots/scroll.js
index 1681cd3f0d..1493dcd80c 100644
--- a/blots/scroll.js
+++ b/blots/scroll.js
@@ -1,4 +1,4 @@
-import Parchment, { ScrollBlot, ContainerBlot } from 'parchment';
+import { Scope, ScrollBlot, ContainerBlot } from 'parchment';
import Emitter from '../core/emitter';
import Block, { BlockEmbed } from './block';
import Break from './break';
@@ -9,15 +9,9 @@ function isLine(blot) {
}
class Scroll extends ScrollBlot {
- constructor(domNode, config) {
- super(domNode);
- this.emitter = config.emitter;
- if (Array.isArray(config.whitelist)) {
- this.whitelist = config.whitelist.reduce((whitelist, format) => {
- whitelist[format] = true;
- return whitelist;
- }, {});
- }
+ constructor(registry, domNode, { emitter }) {
+ super(registry, domNode);
+ this.emitter = emitter;
// Some reason fixes composition issues with character languages in Windows/Chrome, Safari
this.domNode.addEventListener('DOMNodeInserted', () => {});
this.optimize();
@@ -63,19 +57,14 @@ class Scroll extends ScrollBlot {
}
formatAt(index, length, format, value) {
- if (this.whitelist != null && !this.whitelist[format]) return;
super.formatAt(index, length, format, value);
this.optimize();
}
insertAt(index, value, def) {
- if (def != null && this.whitelist != null && !this.whitelist[value]) return;
if (index >= this.length()) {
- if (
- def == null ||
- Parchment.query(value, Parchment.Scope.BLOCK) == null
- ) {
- const blot = Parchment.create(this.statics.defaultChild.blotName);
+ if (def == null || this.scroll.query(value, Scope.BLOCK) == null) {
+ const blot = this.scroll.create(this.statics.defaultChild.blotName);
this.appendChild(blot);
if (def == null && value.endsWith('\n')) {
blot.insertAt(0, value.slice(0, -1), def);
@@ -83,7 +72,7 @@ class Scroll extends ScrollBlot {
blot.insertAt(0, value, def);
}
} else {
- const embed = Parchment.create(value, def);
+ const embed = this.scroll.create(value, def);
this.appendChild(embed);
}
} else {
@@ -93,8 +82,8 @@ class Scroll extends ScrollBlot {
}
insertBefore(blot, ref) {
- if (blot.statics.scope === Parchment.Scope.INLINE_BLOT) {
- const wrapper = Parchment.create(this.statics.defaultChild.blotName);
+ if (blot.statics.scope === Scope.INLINE_BLOT) {
+ const wrapper = this.scroll.create(this.statics.defaultChild.blotName);
wrapper.appendChild(blot);
super.insertBefore(wrapper, ref);
} else {
diff --git a/core.js b/core.js
index 5f85d704a3..052ad45935 100644
--- a/core.js
+++ b/core.js
@@ -1,4 +1,3 @@
-import Parchment from 'parchment';
import Quill from './core/quill';
import Block, { BlockEmbed } from './blots/block';
@@ -32,6 +31,4 @@ Quill.register({
'modules/uploader': Uploader,
});
-Parchment.register(Block, Break, Cursor, Inline, Scroll, TextBlot);
-
export default Quill;
diff --git a/core/editor.js b/core/editor.js
index 1143bff43b..b55c002c38 100644
--- a/core/editor.js
+++ b/core/editor.js
@@ -3,7 +3,7 @@ import equal from 'deep-equal';
import extend from 'extend';
import Delta from 'quill-delta';
import DeltaOp from 'quill-delta/lib/op';
-import Parchment, { LeafBlot } from 'parchment';
+import { LeafBlot } from 'parchment';
import CursorBlot from '../blots/cursor';
import Block, { bubbleFormats } from '../blots/block';
import Break from '../blots/break';
@@ -75,8 +75,6 @@ class Editor {
formatLine(index, length, formats = {}) {
this.scroll.update();
Object.keys(formats).forEach(format => {
- if (this.scroll.whitelist != null && !this.scroll.whitelist[format])
- return;
this.scroll.lines(index, Math.max(length, 1)).forEach(line => {
line.format(format, formats[format]);
});
@@ -187,10 +185,10 @@ class Editor {
mutations.length === 1 &&
mutations[0].type === 'characterData' &&
mutations[0].target.data.match(ASCII) &&
- Parchment.find(mutations[0].target)
+ this.scroll.find(mutations[0].target)
) {
// Optimization for character changes
- const textBlot = Parchment.find(mutations[0].target);
+ const textBlot = this.scroll.find(mutations[0].target);
const formats = bubbleFormats(textBlot);
const index = textBlot.offset(this.scroll);
const oldValue = mutations[0].oldValue.replace(CursorBlot.CONTENTS, '');
diff --git a/core/quill.js b/core/quill.js
index b32a50fad9..8a9c01c02e 100644
--- a/core/quill.js
+++ b/core/quill.js
@@ -1,5 +1,5 @@
import Delta from 'quill-delta';
-import Parchment from 'parchment';
+import * as Parchment from 'parchment';
import extend from 'extend';
import Editor from './editor';
import Emitter from './emitter';
@@ -11,6 +11,8 @@ import Theme from './theme';
const debug = logger('quill');
+const globalRegistry = new Parchment.Registry();
+
class Quill {
static debug(limit) {
if (limit === true) {
@@ -20,7 +22,7 @@ class Quill {
}
static find(node) {
- return instances.get(node) || Parchment.find(node);
+ return instances.get(node) || globalRegistry.find(node);
}
static import(name) {
@@ -50,10 +52,10 @@ class Quill {
(path.startsWith('blots/') || path.startsWith('formats/')) &&
target.blotName !== 'abstract'
) {
- Parchment.register(target);
+ globalRegistry.register(target);
}
if (typeof target.register === 'function') {
- target.register();
+ target.register(globalRegistry);
}
}
}
@@ -79,9 +81,11 @@ class Quill {
this.root.setAttribute('data-gramm', false);
this.scrollingContainer = this.options.scrollingContainer || this.root;
this.emitter = new Emitter();
- this.scroll = Parchment.create(this.root, {
+ const ScrollBlot = this.options.registry.query(
+ Parchment.ScrollBlot.blotName,
+ );
+ this.scroll = new ScrollBlot(this.options.registry, this.root, {
emitter: this.emitter,
- whitelist: this.options.formats,
});
this.editor = new Editor(this.scroll);
this.selection = new Selection(this.scroll, this.emitter);
@@ -169,7 +173,7 @@ class Quill {
let change = new Delta();
if (range == null) {
return change;
- } else if (Parchment.query(name, Parchment.Scope.BLOCK)) {
+ } else if (this.scroll.query(name, Parchment.Scope.BLOCK)) {
change = this.editor.formatLine(range.index, range.length, {
[name]: value,
});
@@ -420,10 +424,10 @@ class Quill {
}
Quill.DEFAULTS = {
bounds: null,
- formats: null,
modules: {},
placeholder: '',
readOnly: false,
+ registry: globalRegistry,
scrollingContainer: null,
theme: 'default',
};
@@ -608,4 +612,4 @@ function shiftRange(range, index, length, source) {
return new Range(start, end - start);
}
-export { expandConfig, overload, Quill as default };
+export { globalRegistry, expandConfig, overload, Quill as default };
diff --git a/core/selection.js b/core/selection.js
index 2bef5cb950..80c42cc6d0 100644
--- a/core/selection.js
+++ b/core/selection.js
@@ -1,4 +1,4 @@
-import Parchment, { LeafBlot, ContainerBlot } from 'parchment';
+import { ContainerBlot, LeafBlot, Scope } from 'parchment';
import clone from 'clone';
import equal from 'deep-equal';
import Emitter from './emitter';
@@ -20,7 +20,7 @@ class Selection {
this.composing = false;
this.mouseDown = false;
this.root = this.scroll.domNode;
- this.cursor = Parchment.create('cursor', this);
+ this.cursor = this.scroll.create('cursor', this);
// savedRange is last non-null range
this.savedRange = new Range(0, 0);
this.lastRange = this.savedRange;
@@ -98,17 +98,16 @@ class Selection {
}
format(format, value) {
- if (this.scroll.whitelist != null && !this.scroll.whitelist[format]) return;
this.scroll.update();
const nativeRange = this.getNativeRange();
if (
nativeRange == null ||
!nativeRange.native.collapsed ||
- Parchment.query(format, Parchment.Scope.BLOCK)
+ this.scroll.query(format, Scope.BLOCK)
)
return;
if (nativeRange.start.node !== this.cursor.textNode) {
- const blot = Parchment.find(nativeRange.start.node, false);
+ const blot = this.scroll.find(nativeRange.start.node, false);
if (blot == null) return;
// TODO Give blot ability to not split
if (blot instanceof LeafBlot) {
@@ -199,7 +198,7 @@ class Selection {
}
const indexes = positions.map(position => {
const [node, offset] = position;
- const blot = Parchment.find(node, true);
+ const blot = this.scroll.find(node, true);
const index = blot.offset(this.scroll);
if (offset === 0) {
return index;
diff --git a/formats/align.js b/formats/align.js
index 20e1c71d52..65f1bf82bf 100644
--- a/formats/align.js
+++ b/formats/align.js
@@ -1,11 +1,7 @@
-import Parchment, {
- Attributor,
- ClassAttributor,
- StyleAttributor,
-} from 'parchment';
+import { Attributor, ClassAttributor, Scope, StyleAttributor } from 'parchment';
const config = {
- scope: Parchment.Scope.BLOCK,
+ scope: Scope.BLOCK,
whitelist: ['right', 'center', 'justify'],
};
diff --git a/formats/background.js b/formats/background.js
index df858ff779..07c764d0ff 100644
--- a/formats/background.js
+++ b/formats/background.js
@@ -1,11 +1,11 @@
-import Parchment, { ClassAttributor } from 'parchment';
+import { ClassAttributor, Scope } from 'parchment';
import { ColorAttributor } from './color';
const BackgroundClass = new ClassAttributor('background', 'ql-bg', {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
});
const BackgroundStyle = new ColorAttributor('background', 'background-color', {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
});
export { BackgroundClass, BackgroundStyle };
diff --git a/formats/color.js b/formats/color.js
index a7628e2793..eb5f6ef391 100644
--- a/formats/color.js
+++ b/formats/color.js
@@ -1,4 +1,4 @@
-import Parchment, { ClassAttributor, StyleAttributor } from 'parchment';
+import { ClassAttributor, Scope, StyleAttributor } from 'parchment';
class ColorAttributor extends StyleAttributor {
value(domNode) {
@@ -14,10 +14,10 @@ class ColorAttributor extends StyleAttributor {
}
const ColorClass = new ClassAttributor('color', 'ql-color', {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
});
const ColorStyle = new ColorAttributor('color', 'color', {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
});
export { ColorAttributor, ColorClass, ColorStyle };
diff --git a/formats/direction.js b/formats/direction.js
index 4c8ce69a58..24fcd82542 100644
--- a/formats/direction.js
+++ b/formats/direction.js
@@ -1,11 +1,7 @@
-import Parchment, {
- Attributor,
- ClassAttributor,
- StyleAttributor,
-} from 'parchment';
+import { Attributor, ClassAttributor, Scope, StyleAttributor } from 'parchment';
const config = {
- scope: Parchment.Scope.BLOCK,
+ scope: Scope.BLOCK,
whitelist: ['rtl'],
};
diff --git a/formats/font.js b/formats/font.js
index d9d8551ada..95b4764846 100644
--- a/formats/font.js
+++ b/formats/font.js
@@ -1,7 +1,7 @@
-import Parchment, { ClassAttributor, StyleAttributor } from 'parchment';
+import { ClassAttributor, Scope, StyleAttributor } from 'parchment';
const config = {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
whitelist: ['serif', 'monospace'],
};
diff --git a/formats/indent.js b/formats/indent.js
index 89d66f5037..e41f80dd40 100644
--- a/formats/indent.js
+++ b/formats/indent.js
@@ -1,4 +1,4 @@
-import Parchment, { ClassAttributor } from 'parchment';
+import { ClassAttributor, Scope } from 'parchment';
class IndentAttributor extends ClassAttributor {
add(node, value) {
@@ -23,7 +23,7 @@ class IndentAttributor extends ClassAttributor {
}
const IndentClass = new IndentAttributor('indent', 'ql-indent', {
- scope: Parchment.Scope.BLOCK,
+ scope: Scope.BLOCK,
whitelist: [1, 2, 3, 4, 5, 6, 7, 8],
});
diff --git a/formats/list.js b/formats/list.js
index 4aef663bd7..40e2e2be5a 100644
--- a/formats/list.js
+++ b/formats/list.js
@@ -21,11 +21,11 @@ class ListItem extends Block {
Quill.register(ListContainer);
}
- constructor(domNode) {
- super(domNode);
+ constructor(scroll, domNode) {
+ super(scroll, domNode);
const listEventHandler = e => {
if (e.target !== domNode) return;
- const format = this.statics.formats(domNode);
+ const format = this.statics.formats(domNode, scroll);
if (format === 'checked') {
this.format('list', 'unchecked');
} else if (format === 'unchecked') {
diff --git a/formats/size.js b/formats/size.js
index b7677d8ece..1f84a6f4e4 100644
--- a/formats/size.js
+++ b/formats/size.js
@@ -1,11 +1,11 @@
-import Parchment, { ClassAttributor, StyleAttributor } from 'parchment';
+import { ClassAttributor, Scope, StyleAttributor } from 'parchment';
const SizeClass = new ClassAttributor('size', 'ql-size', {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
whitelist: ['small', 'large', 'huge'],
});
const SizeStyle = new StyleAttributor('size', 'font-size', {
- scope: Parchment.Scope.INLINE,
+ scope: Scope.INLINE,
whitelist: ['10px', '18px', '32px'],
});
diff --git a/formats/table.js b/formats/table.js
index bcda0931c2..8d40b767d1 100644
--- a/formats/table.js
+++ b/formats/table.js
@@ -1,4 +1,3 @@
-import Parchment from 'parchment';
import Block from '../blots/block';
import Container from '../blots/container';
@@ -84,7 +83,7 @@ class TableContainer extends Container {
if (row.children.head != null) {
value = TableCell.formats(row.children.head.domNode);
}
- const blot = Parchment.create(TableCell.blotName, value);
+ const blot = this.scroll.create(TableCell.blotName, value);
row.appendChild(blot);
blot.optimize(); // Add break blot
});
@@ -107,7 +106,7 @@ class TableContainer extends Container {
if (body == null || body.children.head == null) return;
body.children.forEach(row => {
const ref = row.children.at(index);
- const cell = Parchment.create(TableCell.blotName);
+ const cell = this.scroll.create(TableCell.blotName);
row.insertBefore(cell, ref);
});
}
@@ -115,9 +114,9 @@ class TableContainer extends Container {
insertRow(index) {
const [body] = this.descendant(TableBody);
if (body == null || body.children.head == null) return;
- const row = Parchment.create(TableRow.blotName);
+ const row = this.scroll.create(TableRow.blotName);
body.children.head.children.forEach(() => {
- const cell = Parchment.create(TableCell.blotName);
+ const cell = this.scroll.create(TableCell.blotName);
row.appendChild(cell);
});
const ref = body.children.at(index);
diff --git a/modules/clipboard.js b/modules/clipboard.js
index f5e32744cc..6b4905dea1 100644
--- a/modules/clipboard.js
+++ b/modules/clipboard.js
@@ -1,9 +1,10 @@
import extend from 'extend';
import Delta from 'quill-delta';
-import Parchment, {
+import {
Attributor,
ClassAttributor,
EmbedBlot,
+ Scope,
StyleAttributor,
} from 'parchment';
import Quill from '../core/quill';
@@ -92,6 +93,7 @@ class Clipboard extends Module {
const nodeMatches = new WeakMap();
const [elementMatchers, textMatchers] = this.prepareMatching(nodeMatches);
let delta = traverse(
+ this.quill.scroll,
this.container,
elementMatchers,
textMatchers,
@@ -255,15 +257,16 @@ function isLine(node) {
return ['block', 'list-item', 'table-cell'].indexOf(style.display) > -1;
}
-function traverse(node, elementMatchers, textMatchers, nodeMatches) {
+function traverse(scroll, node, elementMatchers, textMatchers, nodeMatches) {
// Post-order
if (node.nodeType === node.TEXT_NODE) {
return textMatchers.reduce((delta, matcher) => {
- return matcher(node, delta);
+ return matcher(node, delta, scroll);
}, new Delta());
} else if (node.nodeType === node.ELEMENT_NODE) {
return Array.from(node.childNodes || []).reduce((delta, childNode) => {
let childrenDelta = traverse(
+ scroll,
childNode,
elementMatchers,
textMatchers,
@@ -271,11 +274,11 @@ function traverse(node, elementMatchers, textMatchers, nodeMatches) {
);
if (childNode.nodeType === node.ELEMENT_NODE) {
childrenDelta = elementMatchers.reduce((reducedDelta, matcher) => {
- return matcher(childNode, reducedDelta);
+ return matcher(childNode, reducedDelta, scroll);
}, childrenDelta);
childrenDelta = (nodeMatches.get(childNode) || []).reduce(
(reducedDelta, matcher) => {
- return matcher(childNode, reducedDelta);
+ return matcher(childNode, reducedDelta, scroll);
},
childrenDelta,
);
@@ -290,7 +293,7 @@ function matchAlias(format, node, delta) {
return applyFormat(delta, format, true);
}
-function matchAttributor(node, delta) {
+function matchAttributor(node, delta, scroll) {
const attributes = Attributor.keys(node);
const classes = ClassAttributor.keys(node);
const styles = StyleAttributor.keys(node);
@@ -299,7 +302,7 @@ function matchAttributor(node, delta) {
.concat(classes)
.concat(styles)
.forEach(name => {
- let attr = Parchment.query(name, Parchment.Scope.ATTRIBUTE);
+ let attr = scroll.query(name, Scope.ATTRIBUTE);
if (attr != null) {
formats[attr.attrName] = attr.value(node);
if (formats[attr.attrName]) return;
@@ -320,18 +323,18 @@ function matchAttributor(node, delta) {
return delta;
}
-function matchBlot(node, delta) {
- const match = Parchment.query(node);
+function matchBlot(node, delta, scroll) {
+ const match = scroll.query(node);
if (match == null) return delta;
if (match.prototype instanceof EmbedBlot) {
const embed = {};
const value = match.value(node);
if (value != null) {
embed[match.blotName] = value;
- return new Delta().insert(embed, match.formats(node));
+ return new Delta().insert(embed, match.formats(node, scroll));
}
} else if (typeof match.formats === 'function') {
- return applyFormat(delta, match.blotName, match.formats(node));
+ return applyFormat(delta, match.blotName, match.formats(node, scroll));
}
return delta;
}
@@ -352,8 +355,8 @@ function matchIgnore() {
return new Delta();
}
-function matchIndent(node, delta) {
- const match = Parchment.query(node);
+function matchIndent(node, delta, scroll) {
+ const match = scroll.query(node);
if (
match == null ||
match.blotName !== 'list' ||
@@ -364,7 +367,7 @@ function matchIndent(node, delta) {
let indent = -1;
let parent = node.parentNode;
while (!parent.classList.contains('ql-clipboard')) {
- if ((Parchment.query(parent) || {}).blotName === 'list-container') {
+ if ((scroll.query(parent) || {}).blotName === 'list-container') {
indent += 1;
}
parent = parent.parentNode;
diff --git a/modules/history.js b/modules/history.js
index 4df4d52f3c..312afdbc46 100644
--- a/modules/history.js
+++ b/modules/history.js
@@ -1,4 +1,4 @@
-import Parchment from 'parchment';
+import { Scope } from 'parchment';
import Quill from '../core/quill';
import Module from '../core/module';
@@ -43,7 +43,7 @@ class History extends Module {
this.ignoreChange = true;
this.quill.updateContents(delta[source], Quill.sources.USER);
this.ignoreChange = false;
- const index = getLastChangeIndex(delta[source]);
+ const index = getLastChangeIndex(this.quill.scroll, delta[source]);
this.quill.setSelection(index);
}
@@ -104,7 +104,7 @@ History.DEFAULTS = {
userOnly: false,
};
-function endsWithNewlineChange(delta) {
+function endsWithNewlineChange(scroll, delta) {
const lastOp = delta.ops[delta.ops.length - 1];
if (lastOp == null) return false;
if (lastOp.insert != null) {
@@ -112,18 +112,18 @@ function endsWithNewlineChange(delta) {
}
if (lastOp.attributes != null) {
return Object.keys(lastOp.attributes).some(attr => {
- return Parchment.query(attr, Parchment.Scope.BLOCK) != null;
+ return scroll.query(attr, Scope.BLOCK) != null;
});
}
return false;
}
-function getLastChangeIndex(delta) {
+function getLastChangeIndex(scroll, delta) {
const deleteLength = delta.reduce((length, op) => {
return length + (op.delete || 0);
}, 0);
let changeIndex = delta.length() - deleteLength;
- if (endsWithNewlineChange(delta)) {
+ if (endsWithNewlineChange(scroll, delta)) {
changeIndex -= 1;
}
return changeIndex;
diff --git a/modules/keyboard.js b/modules/keyboard.js
index d85b2147c9..34bc2b9d77 100644
--- a/modules/keyboard.js
+++ b/modules/keyboard.js
@@ -3,7 +3,7 @@ import equal from 'deep-equal';
import extend from 'extend';
import Delta from 'quill-delta';
import DeltaOp from 'quill-delta/lib/op';
-import Parchment, { EmbedBlot, TextBlot } from 'parchment';
+import { EmbedBlot, Scope, TextBlot } from 'parchment';
import Quill from '../core/quill';
import logger from '../core/logger';
import Module from '../core/module';
@@ -28,13 +28,6 @@ class Keyboard extends Module {
super(quill, options);
this.bindings = {};
Object.keys(this.options.bindings).forEach(name => {
- if (
- name === 'list autofill' &&
- quill.scroll.whitelist != null &&
- !quill.scroll.whitelist.list
- ) {
- return;
- }
if (this.options.bindings[name]) {
this.addBinding(this.options.bindings[name]);
}
@@ -313,6 +306,7 @@ Keyboard.DEFAULTS = {
format: { list: false },
prefix: /^\s*?(\d+\.|-|\*|\[ ?\]|\[x\])$/,
handler(range, context) {
+ if (this.quill.scroll.query('list') == null) return true;
const { length } = context.prefix;
const [line, offset] = this.quill.getLine(range.index);
if (offset > length) return true;
@@ -461,7 +455,7 @@ function handleEnter(range, context) {
}
const lineFormats = Object.keys(context.format).reduce((formats, format) => {
if (
- Parchment.query(format, Parchment.Scope.BLOCK) &&
+ this.quill.scroll.query(format, Scope.BLOCK) &&
!Array.isArray(context.format[format])
) {
formats[format] = context.format[format];
@@ -487,7 +481,7 @@ function makeCodeBlockHandler(indent) {
shiftKey: !indent,
format: { 'code-block': true },
handler(range) {
- const CodeBlock = Parchment.query('code-block');
+ const CodeBlock = this.quill.scroll.query('code-block');
const lines =
range.length === 0
? this.quill.getLines(range.index, 1)
diff --git a/modules/toolbar.js b/modules/toolbar.js
index 2897da253b..a16923ec0a 100644
--- a/modules/toolbar.js
+++ b/modules/toolbar.js
@@ -1,5 +1,5 @@
import Delta from 'quill-delta';
-import Parchment, { EmbedBlot } from 'parchment';
+import { EmbedBlot, Scope } from 'parchment';
import Quill from '../core/quill';
import logger from '../core/logger';
import Module from '../core/module';
@@ -57,18 +57,12 @@ class Toolbar extends Module {
if (input.tagName === 'BUTTON') {
input.setAttribute('type', 'button');
}
- if (this.handlers[format] == null) {
- if (
- this.quill.scroll.whitelist != null &&
- this.quill.scroll.whitelist[format] == null
- ) {
- debug.warn('ignoring attaching to disabled format', format, input);
- return;
- }
- if (Parchment.query(format) == null) {
- debug.warn('ignoring attaching to nonexistent format', format, input);
- return;
- }
+ if (
+ this.handlers[format] == null &&
+ this.quill.scroll.query(format) == null
+ ) {
+ debug.warn('ignoring attaching to nonexistent format', format, input);
+ return;
}
const eventName = input.tagName === 'SELECT' ? 'change' : 'click';
input.addEventListener(eventName, e => {
@@ -93,7 +87,9 @@ class Toolbar extends Module {
const [range] = this.quill.selection.getRange();
if (this.handlers[format] != null) {
this.handlers[format].call(this, value);
- } else if (Parchment.query(format).prototype instanceof EmbedBlot) {
+ } else if (
+ this.quill.scroll.query(format).prototype instanceof EmbedBlot
+ ) {
value = prompt(`Enter ${format}`); // eslint-disable-line no-alert
if (!value) return;
this.quill.updateContents(
@@ -212,7 +208,7 @@ Toolbar.DEFAULTS = {
const formats = this.quill.getFormat();
Object.keys(formats).forEach(name => {
// Clean functionality in existing apps only clean inline formats
- if (Parchment.query(name, Parchment.Scope.INLINE) != null) {
+ if (this.quill.scroll.query(name, Scope.INLINE) != null) {
this.quill.format(name, false, Quill.sources.USER);
}
});
diff --git a/package.json b/package.json
index 332d2bea5c..2b0f3920a1 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"deep-equal": "^1.0.1",
"eventemitter3": "^3.1.0",
"extend": "^3.0.1",
- "parchment": "quilljs/parchment#0928cfdd220bb2b1636583c1f667e07341816736",
+ "parchment": "quilljs/parchment#487850f7eb030a6c4e750ba809e58b09444e0bdb",
"quill-delta": "^3.6.2"
},
"devDependencies": {
diff --git a/test/helpers/unit.js b/test/helpers/unit.js
index b5afd45a3d..c11bbaaab9 100644
--- a/test/helpers/unit.js
+++ b/test/helpers/unit.js
@@ -3,7 +3,7 @@ import Editor from '../../core/editor';
import Emitter from '../../core/emitter';
import Selection from '../../core/selection';
import Scroll from '../../blots/scroll';
-import Quill from '../../core/quill';
+import Quill, { globalRegistry } from '../../core/quill';
const div = document.createElement('div');
div.id = 'test-container';
@@ -110,7 +110,7 @@ function initialize(klass, html, container = this.container) {
if (klass === HTMLElement) return container;
if (klass === Quill) return new Quill(container);
const emitter = new Emitter();
- const scroll = new Scroll(container, { emitter });
+ const scroll = new Scroll(globalRegistry, container, { emitter });
if (klass === Scroll) return scroll;
if (klass === Editor) return new Editor(scroll);
if (klass === Selection) return new Selection(scroll, emitter);
diff --git a/test/unit/blots/block.js b/test/unit/blots/block.js
index 5f2aaa09d2..eda24bf6d5 100644
--- a/test/unit/blots/block.js
+++ b/test/unit/blots/block.js
@@ -1,15 +1,16 @@
-import Parchment from 'parchment';
import Scroll from '../../../blots/scroll';
describe('Block', function() {
it('childless', function() {
- const block = Parchment.create('block');
+ const scroll = this.initialize(Scroll, '');
+ const block = scroll.create('block');
block.optimize();
expect(block.domNode).toEqualHTML('
');
});
it('insert into empty', function() {
- const block = Parchment.create('block');
+ const scroll = this.initialize(Scroll, '');
+ const block = scroll.create('block');
block.insertAt(0, 'Test');
expect(block.domNode).toEqualHTML('Test');
});
diff --git a/test/unit/blots/scroll.js b/test/unit/blots/scroll.js
index 8dcd2ae2ad..92926432ae 100644
--- a/test/unit/blots/scroll.js
+++ b/test/unit/blots/scroll.js
@@ -1,4 +1,3 @@
-import Parchment from 'parchment';
import Emitter from '../../../core/emitter';
import Selection, { Range } from '../../../core/selection';
import Cursor from '../../../blots/cursor';
@@ -40,19 +39,6 @@ describe('Scroll', function() {
}, 1);
});
- it('whitelist', function() {
- const scroll = Parchment.create('scroll', {
- emitter: new Emitter(),
- whitelist: ['bold'],
- });
- scroll.insertAt(0, 'Hello World!');
- scroll.formatAt(0, 5, 'bold', true);
- scroll.formatAt(6, 5, 'italic', true);
- expect(scroll.domNode.firstChild).toEqualHTML(
- 'Hello World!',
- );
- });
-
describe('leaf()', function() {
it('text', function() {
const scroll = this.initialize(Scroll, '
Tests
'); diff --git a/test/unit/modules/history.js b/test/unit/modules/history.js index e554ac439a..d4e3156762 100644 --- a/test/unit/modules/history.js +++ b/test/unit/modules/history.js @@ -1,12 +1,13 @@ import Delta from 'quill-delta'; import Quill from '../../../core'; +import { globalRegistry } from '../../../core/quill'; import { getLastChangeIndex } from '../../../modules/history'; describe('History', function() { describe('getLastChangeIndex', function() { it('delete', function() { const delta = new Delta().retain(4).delete(2); - expect(getLastChangeIndex(delta)).toEqual(4); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(4); }); it('delete with inserts', function() { @@ -14,17 +15,17 @@ describe('History', function() { .retain(4) .insert('test') .delete(2); - expect(getLastChangeIndex(delta)).toEqual(8); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(8); }); it('insert text', function() { const delta = new Delta().retain(4).insert('testing'); - expect(getLastChangeIndex(delta)).toEqual(11); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(11); }); it('insert embed', function() { const delta = new Delta().retain(4).insert({ image: true }); - expect(getLastChangeIndex(delta)).toEqual(5); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(5); }); it('insert with deletes', function() { @@ -32,34 +33,34 @@ describe('History', function() { .retain(4) .delete(3) .insert('!'); - expect(getLastChangeIndex(delta)).toEqual(5); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(5); }); it('format', function() { const delta = new Delta().retain(4).retain(3, { bold: true }); - expect(getLastChangeIndex(delta)).toEqual(7); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(7); }); it('format newline', function() { const delta = new Delta().retain(4).retain(1, { align: 'left' }); - expect(getLastChangeIndex(delta)).toEqual(4); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(4); }); it('format mixed', function() { const delta = new Delta() .retain(4) .retain(1, { align: 'left', bold: true }); - expect(getLastChangeIndex(delta)).toEqual(4); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(4); }); it('insert newline', function() { const delta = new Delta().retain(4).insert('a\n'); - expect(getLastChangeIndex(delta)).toEqual(5); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(5); }); it('mutliple newline inserts', function() { const delta = new Delta().retain(4).insert('ab\n\n'); - expect(getLastChangeIndex(delta)).toEqual(7); + expect(getLastChangeIndex(globalRegistry, delta)).toEqual(7); }); });