diff --git a/README.md b/README.md index 4299ec11..b683c535 100644 --- a/README.md +++ b/README.md @@ -395,12 +395,14 @@ YTextEvents compute changes as deltas.
format(index:number, length:number, formattingAttributes:Object<string,string>)
applyDelta(delta)
- applyDelta(delta, opts:Object<string,any>)
+ ytext.applyDelta(delta, { sanitize: false })+
length:number
- permitEmptyParagraph(permit:boolean)
- toString():string
toJSON():string
diff --git a/src/types/YText.js b/src/types/YText.js
index 1a5ca05e..31998b21 100644
--- a/src/types/YText.js
+++ b/src/types/YText.js
@@ -848,10 +848,13 @@ export class YText extends AbstractType {
* Apply a {@link Delta} on this shared YText type.
*
* @param {any} delta The changes to apply on this element.
+ * @param {object} [opts]
+ * @param {boolean} [opts.sanitize] Sanitize input delta. Removes ending newlines if set to true.
+ *
*
* @public
*/
- applyDelta (delta) {
+ applyDelta (delta, { sanitize = true } = {}) {
if (this.doc !== null) {
transact(this.doc, transaction => {
/**
@@ -861,8 +864,16 @@ export class YText extends AbstractType {
const currentAttributes = new Map()
for (let i = 0; i < delta.length; i++) {
const op = delta[i]
- if (op.insert !== undefined && (typeof op.insert !== 'string' || op.insert.length > 0)) {
- pos = insertText(transaction, this, pos.left, pos.right, currentAttributes, op.insert, op.attributes || {})
+ if (op.insert !== undefined) {
+ // Quill assumes that the content starts with an empty paragraph.
+ // Yjs/Y.Text assumes that it starts empty. We always hide that
+ // there is a newline at the end of the content.
+ // If we omit this step, clients will see a different number of
+ // paragraphs, but nothing bad will happen.
+ const ins = (!sanitize && typeof op.insert === 'string' && i === delta.length - 1 && pos.right === null && op.insert.slice(-1) === '\n') ? op.insert.slice(0, -1) : op.insert
+ if (typeof ins !== 'string' || ins.length > 0) {
+ pos = insertText(transaction, this, pos.left, pos.right, currentAttributes, ins, op.attributes || {})
+ }
} else if (op.retain !== undefined) {
pos = formatText(transaction, this, pos.left, pos.right, currentAttributes, op.retain, op.attributes || {})
} else if (op.delete !== undefined) {