Comparing version 1.1.0 to 1.1.1
@@ -25,2 +25,3 @@ import Parchment from 'parchment'; | ||
this.optimize(); | ||
this.enable(); | ||
} | ||
@@ -44,2 +45,6 @@ | ||
enable(enabled = true) { | ||
this.domNode.setAttribute('contenteditable', enabled); | ||
} | ||
formatAt(index, length, format, value) { | ||
@@ -46,0 +51,0 @@ if (this.whitelist != null && !this.whitelist[format]) return; |
@@ -0,1 +1,16 @@ | ||
# 1.1.1 | ||
### Bug fixes | ||
- TEXT_CHANGE event now use cursor position to inform change location [#746](https://github.com/quilljs/quill/issues/746) | ||
- Fix inconsistent cursor reporting between browsers [#1007](https://github.com/quilljs/quill/issues/1007) | ||
- Fix tooltip overflow in docs [#1060](https://github.com/quilljs/quill/issues/1060) | ||
- Fix naming [#1063](https://github.com/quilljs/quill/pull/1063) | ||
- Fix Medium example [#1064](https://github.com/quilljs/quill/issues/1064) | ||
Thanks to [@artaommahe](https://github.com/artaommahe), [@benbro](https://github.com/benbro), [@fuffalist](https://github.com/fuffalist), [@sachinrekhi](https://github.com/sachinrekhi), [@sergop321](https://github.com/sergop321), and [@tlg](https://github.com/tlg) for contributions to this release! | ||
Special thanks to [@DadaMonad](https://github.com/DadaMonad) for contributions on [fast-diff](https://github.com/jhchen/fast-diff) that enabled the [#746](https://github.com/quilljs/quill/issues/746) fix. | ||
# 1.1.0 | ||
@@ -2,0 +17,0 @@ |
import Delta from 'quill-delta'; | ||
import DeltaOp from 'quill-delta/lib/op'; | ||
import Emitter from './emitter'; | ||
import Parchment from 'parchment'; | ||
@@ -14,11 +13,8 @@ import CodeBlock from '../formats/code'; | ||
class Editor { | ||
constructor(scroll, emitter) { | ||
constructor(scroll) { | ||
this.scroll = scroll; | ||
this.emitter = emitter; | ||
this.emitter.on(Emitter.events.SCROLL_UPDATE, this.update.bind(this, null)); | ||
this.delta = this.getDelta(); | ||
this.enable(); | ||
} | ||
applyDelta(delta, source = Emitter.sources.API) { | ||
applyDelta(delta) { | ||
let consumeNextNewline = false; | ||
@@ -29,3 +25,3 @@ this.scroll.update(); | ||
delta = normalizeDelta(delta); | ||
delta.ops.reduce((index, op) => { | ||
delta.reduce((index, op) => { | ||
let length = op.retain || op.delete || op.insert.length || 1; | ||
@@ -63,3 +59,3 @@ let attributes = op.attributes || {}; | ||
}, 0); | ||
delta.ops.reduce((index, op) => { | ||
delta.reduce((index, op) => { | ||
if (typeof op.delete === 'number') { | ||
@@ -73,15 +69,11 @@ this.scroll.deleteAt(index, op.delete); | ||
this.scroll.optimize(); | ||
return this.update(delta, source); | ||
return this.update(delta); | ||
} | ||
deleteText(index, length, source = Emitter.sources.API) { | ||
deleteText(index, length) { | ||
this.scroll.deleteAt(index, length); | ||
return this.update(new Delta().retain(index).delete(length), source); | ||
return this.update(new Delta().retain(index).delete(length)); | ||
} | ||
enable(enabled = true) { | ||
this.scroll.domNode.setAttribute('contenteditable', enabled); | ||
} | ||
formatLine(index, length, formats = {}, source = Emitter.sources.API) { | ||
formatLine(index, length, formats = {}) { | ||
this.scroll.update(); | ||
@@ -104,10 +96,10 @@ Object.keys(formats).forEach((format) => { | ||
this.scroll.optimize(); | ||
return this.update(new Delta().retain(index).retain(length, clone(formats)), source); | ||
return this.update(new Delta().retain(index).retain(length, clone(formats))); | ||
} | ||
formatText(index, length, formats = {}, source = Emitter.sources.API) { | ||
formatText(index, length, formats = {}) { | ||
Object.keys(formats).forEach((format) => { | ||
this.scroll.formatAt(index, length, format, formats[format]); | ||
}); | ||
return this.update(new Delta().retain(index).retain(length, clone(formats)), source); | ||
return this.update(new Delta().retain(index).retain(length, clone(formats))); | ||
} | ||
@@ -154,13 +146,15 @@ | ||
getText(index, length) { | ||
return this.getContents(index, length).ops.map(function(op) { | ||
return (typeof op.insert === 'string') ? op.insert : ''; | ||
return this.getContents(index, length).filter(function(op) { | ||
return typeof op.insert === 'string'; | ||
}).map(function(op) { | ||
return op.insert; | ||
}).join(''); | ||
} | ||
insertEmbed(index, embed, value, source = Emitter.sources.API) { | ||
insertEmbed(index, embed, value) { | ||
this.scroll.insertAt(index, embed, value); | ||
return this.update(new Delta().retain(index).insert({ [embed]: value }), source); | ||
return this.update(new Delta().retain(index).insert({ [embed]: value })); | ||
} | ||
insertText(index, text, formats = {}, source = Emitter.sources.API) { | ||
insertText(index, text, formats = {}) { | ||
text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); | ||
@@ -171,3 +165,3 @@ this.scroll.insertAt(index, text); | ||
}); | ||
return this.update(new Delta().retain(index).insert(text, clone(formats)), source) | ||
return this.update(new Delta().retain(index).insert(text, clone(formats))); | ||
} | ||
@@ -182,3 +176,3 @@ | ||
removeFormat(index, length, source) { | ||
removeFormat(index, length) { | ||
let text = this.getText(index, length); | ||
@@ -198,6 +192,6 @@ let [line, offset] = this.scroll.line(index + length); | ||
let delta = new Delta().retain(index).concat(diff); | ||
return this.applyDelta(delta, source); | ||
return this.applyDelta(delta); | ||
} | ||
update(change, source = Emitter.sources.USER, mutations = []) { | ||
update(change, mutations = [], cursorIndex = undefined) { | ||
let oldDelta = this.delta; | ||
@@ -214,4 +208,4 @@ if (mutations.length === 1 && | ||
let newText = new Delta().insert(textBlot.value()); | ||
let diffDelta = new Delta().retain(index).concat(oldText.diff(newText)); | ||
change = diffDelta.ops.reduce(function(delta, op) { | ||
let diffDelta = new Delta().retain(index).concat(oldText.diff(newText, cursorIndex)); | ||
change = diffDelta.reduce(function(delta, op) { | ||
if (op.insert) { | ||
@@ -227,12 +221,5 @@ return delta.insert(op.insert, formats); | ||
if (!change || !equal(oldDelta.compose(change), this.delta)) { | ||
change = oldDelta.diff(this.delta); | ||
change = oldDelta.diff(this.delta, cursorIndex); | ||
} | ||
} | ||
if (change.length() > 0) { | ||
let args = [Emitter.events.TEXT_CHANGE, change, oldDelta, source]; | ||
this.emitter.emit(Emitter.events.EDITOR_CHANGE, ...args); | ||
if (source !== Emitter.sources.SILENT) { | ||
this.emitter.emit(...args); | ||
} | ||
} | ||
return change; | ||
@@ -260,3 +247,3 @@ } | ||
function normalizeDelta(delta) { | ||
return delta.ops.reduce(function(delta, op) { | ||
return delta.reduce(function(delta, op) { | ||
if (op.insert === 1) { | ||
@@ -263,0 +250,0 @@ let attributes = clone(op.attributes); |
@@ -68,3 +68,3 @@ import './polyfill'; | ||
}); | ||
this.editor = new Editor(this.scroll, this.emitter); | ||
this.editor = new Editor(this.scroll); | ||
this.selection = new Selection(this.scroll, this.emitter); | ||
@@ -81,2 +81,9 @@ this.theme = new this.options.theme(this, this.options); | ||
}); | ||
this.emitter.on(Emitter.events.SCROLL_UPDATE, (source, mutations) => { | ||
let range = this.selection.lastRange; | ||
let index = range && range.length === 0 ? range.index : undefined; | ||
modify.call(this, () => { | ||
return this.editor.update(null, mutations, index); | ||
}, source); | ||
}); | ||
let contents = this.clipboard.convert(`<div class='ql-editor' style="white-space: normal;">${html}<p><br></p></div>`); | ||
@@ -109,5 +116,5 @@ this.setContents(contents); | ||
[index, length, , source] = overload(index, length, source); | ||
return modify.call(this, source, index, -1*length, () => { | ||
return this.editor.deleteText(index, length, source); | ||
}); | ||
return modify.call(this, () => { | ||
return this.editor.deleteText(index, length); | ||
}, source, index, -1*length); | ||
} | ||
@@ -120,3 +127,3 @@ | ||
enable(enabled = true) { | ||
this.editor.enable(enabled); | ||
this.scroll.enable(enabled); | ||
this.container.classList.toggle('ql-disabled', !enabled); | ||
@@ -134,18 +141,18 @@ if (!enabled) { | ||
format(name, value, source = Emitter.sources.API) { | ||
if (!this.options.strict && !this.isEnabled() && source === Emitter.sources.USER) { | ||
return new Delta(); | ||
} | ||
let range = this.getSelection(true); | ||
let change = new Delta(); | ||
if (range == null) return change; | ||
if (Parchment.query(name, Parchment.Scope.BLOCK)) { | ||
change = this.formatLine(range, name, value, source); | ||
} else if (range.length === 0) { | ||
this.selection.format(name, value); | ||
return modify.call(this, () => { | ||
let range = this.getSelection(true); | ||
let change = new Delta(); | ||
if (range == null) { | ||
return change; | ||
} else if (Parchment.query(name, Parchment.Scope.BLOCK)) { | ||
change = this.editor.formatLine(range.index, range.length, { [name]: value }); | ||
} else if (range.length === 0) { | ||
this.selection.format(name, value); | ||
return change; | ||
} else { | ||
change = this.editor.formatText(range.index, range.length, { [name]: value }); | ||
} | ||
this.setSelection(range, Emitter.sources.SILENT); | ||
return change; | ||
} else { | ||
change = this.formatText(range, name, value, source); | ||
} | ||
this.setSelection(range, Emitter.sources.SILENT); | ||
return change; | ||
}, source); | ||
} | ||
@@ -156,5 +163,5 @@ | ||
[index, length, formats, source] = overload(index, length, name, value, source); | ||
return modify.call(this, source, index, 0, () => { | ||
return this.editor.formatLine(index, length, formats, source); | ||
}); | ||
return modify.call(this, () => { | ||
return this.editor.formatLine(index, length, formats); | ||
}, source, index, 0); | ||
} | ||
@@ -165,5 +172,5 @@ | ||
[index, length, formats, source] = overload(index, length, name, value, source); | ||
return modify.call(this, source, index, 0, () => { | ||
return this.editor.formatText(index, length, formats, source); | ||
}); | ||
return modify.call(this, () => { | ||
return this.editor.formatText(index, length, formats); | ||
}, source, index, 0); | ||
} | ||
@@ -216,5 +223,5 @@ | ||
insertEmbed(index, embed, value, source = Quill.sources.API) { | ||
return modify.call(this, source, index, null, () => { | ||
return this.editor.insertEmbed(index, embed, value, source); | ||
}); | ||
return modify.call(this, () => { | ||
return this.editor.insertEmbed(index, embed, value); | ||
}, source, index); | ||
} | ||
@@ -225,5 +232,5 @@ | ||
[index, , formats, source] = overload(index, 0, name, value, source); | ||
return modify.call(this, source, index, text.length, () => { | ||
return this.editor.insertText(index, text, formats, source); | ||
}); | ||
return modify.call(this, () => { | ||
return this.editor.insertText(index, text, formats); | ||
}, source, index, text.length); | ||
} | ||
@@ -253,19 +260,18 @@ | ||
[index, length, , source] = overload(index, length, source); | ||
return modify.call(this, source, index, null, () => { | ||
return this.editor.removeFormat(index, length, source); | ||
}); | ||
return modify.call(this, () => { | ||
return this.editor.removeFormat(index, length); | ||
}, source, index); | ||
} | ||
setContents(delta, source = Emitter.sources.API) { | ||
if (!this.options.strict && !this.isEnabled() && source === Emitter.sources.USER) { | ||
return new Delta(); | ||
} | ||
delta = new Delta(delta).slice(); | ||
let lastOp = delta.ops[delta.ops.length - 1]; | ||
// Quill contents must always end with newline | ||
if (lastOp == null || lastOp.insert[lastOp.insert.length-1] !== '\n') { | ||
delta.insert('\n'); | ||
} | ||
delta.delete(this.getLength()); | ||
return this.editor.applyDelta(delta, source); | ||
return modify.call(this, () => { | ||
delta = new Delta(delta).slice(); | ||
let lastOp = delta.ops[delta.ops.length - 1]; | ||
// Quill contents must always end with newline | ||
if (lastOp == null || lastOp.insert[lastOp.insert.length-1] !== '\n') { | ||
delta.insert('\n'); | ||
} | ||
delta.delete(this.getLength()); | ||
return this.editor.applyDelta(delta); | ||
}, source); | ||
} | ||
@@ -295,15 +301,8 @@ | ||
updateContents(delta, source = Emitter.sources.API) { | ||
if (!this.options.strict && !this.isEnabled() && source === Emitter.sources.USER) { | ||
return new Delta(); | ||
} | ||
let range = this.getSelection(); | ||
if (Array.isArray(delta)) { | ||
delta = new Delta(delta.slice()); | ||
} | ||
let change = this.editor.applyDelta(delta, source); | ||
if (range != null) { | ||
range = shiftRange(range, change, source); | ||
this.setSelection(range, Emitter.sources.SILENT); | ||
} | ||
return change; | ||
return modify.call(this, () => { | ||
if (Array.isArray(delta)) { | ||
delta = new Delta(delta.slice()); | ||
} | ||
return this.editor.applyDelta(delta, source); | ||
}, source, true); | ||
} | ||
@@ -391,12 +390,15 @@ } | ||
function modify(source, index, shift, modifier) { | ||
let change = new Delta(); | ||
// Handle selection preservation and TEXT_CHANGE emission | ||
// common to modification APIs | ||
function modify(modifier, source, index, shift) { | ||
if (!this.options.strict && !this.isEnabled() && source === Emitter.sources.USER) { | ||
return new Delta(); | ||
} | ||
let range = this.getSelection(); | ||
change = modifier(); | ||
let range = index == null ? null : this.getSelection(); | ||
let oldDelta = this.editor.delta; | ||
let change = modifier(); | ||
if (range != null) { | ||
if (shift === null) { | ||
range = shiftRange(range, index, change, source); | ||
if (index === true) index = range.index; | ||
if (shift == null) { | ||
range = shiftRange(range, change, source); | ||
} else if (shift !== 0) { | ||
@@ -407,2 +409,9 @@ range = shiftRange(range, index, shift, source); | ||
} | ||
if (change.length() > 0) { | ||
let args = [Emitter.events.TEXT_CHANGE, change, oldDelta, source]; | ||
this.emitter.emit(Emitter.events.EDITOR_CHANGE, ...args); | ||
if (source !== Emitter.sources.SILENT) { | ||
this.emitter.emit(...args); | ||
} | ||
} | ||
return change; | ||
@@ -409,0 +418,0 @@ } |
@@ -105,3 +105,3 @@ import Parchment from 'parchment'; | ||
function getLastChangeIndex(delta) { | ||
let deleteLength = delta.ops.reduce(function(length, op) { | ||
let deleteLength = delta.reduce(function(length, op) { | ||
length += (op.delete || 0); | ||
@@ -108,0 +108,0 @@ return length; |
{ | ||
"name": "quill", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "Your powerful, rich text editor", | ||
@@ -40,3 +40,3 @@ "author": "Jason Chen <jhchen7@gmail.com>", | ||
"parchment": "1.0.2", | ||
"quill-delta": "3.2.0" | ||
"quill-delta": "3.4.0" | ||
}, | ||
@@ -46,3 +46,3 @@ "devDependencies": { | ||
"babel-loader": "^6.2.5", | ||
"babel-plugin-istanbul": "^2.0.1", | ||
"babel-plugin-istanbul": "^2.0.3", | ||
"babel-plugin-transform-es2015-modules-commonjs": "^6.16.0", | ||
@@ -52,3 +52,3 @@ "babel-preset-es2015": "^6.14.0", | ||
"eslint": "^3.8.0", | ||
"eslint-loader": "^1.5.0", | ||
"eslint-loader": "^1.6.0", | ||
"extract-text-webpack-plugin": "^1.0.1", | ||
@@ -55,0 +55,0 @@ "html-loader": "~0.4.4", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2105007
22287
+ Addedquill-delta@3.4.0(transitive)
- Removedquill-delta@3.2.0(transitive)
Updatedquill-delta@3.4.0