Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rich-text

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rich-text - npm Package Compare versions

Comparing version 1.1.0 to 2.0.0

CHANGELOG.md

42

lib/delta.js

@@ -23,8 +23,4 @@ var diff = require('fast-diff');

var newOp = {};
if (is.string(text)) {
if (text.length === 0) return this;
newOp.insert = text;
} else if (is.number(text)) {
newOp.insert = text;
}
if (text.length === 0) return this;
newOp.insert = text;
if (is.object(attributes) && Object.keys(attributes).length > 0) newOp.attributes = attributes;

@@ -57,3 +53,3 @@ return this.push(newOp);

// always prefer to insert first
if (is.number(lastOp['delete']) && (is.string(newOp.insert) || is.number(newOp.insert))) {
if (is.number(lastOp['delete']) && newOp.insert != null) {
index -= 1;

@@ -78,3 +74,7 @@ lastOp = this.ops[index - 1];

}
this.ops.splice(index, 0, newOp);
if (index === this.ops.length) {
this.ops.push(newOp);
} else {
this.ops.splice(index, 0, newOp);
}
return this;

@@ -120,8 +120,8 @@ };

var otherIter = op.iterator(other.ops);
this.ops = [];
var delta = new Delta();
while (thisIter.hasNext() || otherIter.hasNext()) {
if (otherIter.peekType() === 'insert') {
this.push(otherIter.next());
delta.push(otherIter.next());
} else if (thisIter.peekType() === 'delete') {
this.push(thisIter.next());
delta.push(thisIter.next());
} else {

@@ -141,19 +141,24 @@ var length = Math.min(thisIter.peekLength(), otherIter.peekLength());

if (attributes) newOp.attributes = attributes;
this.push(newOp);
delta.push(newOp);
// Other op should be delete, we could be an insert or retain
// Insert + delete cancels out
} else if (is.number(otherOp['delete']) && is.number(thisOp.retain)) {
this.push(otherOp);
delta.push(otherOp);
}
}
}
return this.chop();
return delta.chop();
};
Delta.prototype.diff = function (other) {
var delta = new Delta();
if (this.ops === other.ops) {
return delta;
}
var strings = [this.ops, other.ops].map(function (ops) {
return ops.map(function (op) {
if (is.string(op.insert)) return op.insert;
if (is.number(op.insert)) return NULL_CHARACTER;
var prep = ops === other.ops ? 'on' : 'with';
if (op.insert != null) {
return is.string(op.insert) ? op.insert : NULL_CHARACTER;
}
var prep = (ops === other.ops) ? 'on' : 'with';
throw new Error('diff() called ' + prep + ' non-document');

@@ -165,3 +170,2 @@ }).join('');

var otherIter = op.iterator(other.ops);
var delta = new Delta();
diffResult.forEach(function (component) {

@@ -185,3 +189,3 @@ var length = component[1].length;

var otherOp = otherIter.next(opLength);
if (thisOp.insert === otherOp.insert) {
if (is.equal(thisOp.insert, otherOp.insert)) {
delta.retain(opLength, op.attributes.diff(thisOp.attributes, otherOp.attributes));

@@ -188,0 +192,0 @@ } else {

@@ -6,2 +6,3 @@ module.exports = {

if (a == null || b == null) return false;
if (!this.object(a) || !this.object(b)) return false;
if (Object.keys(a).length != Object.keys(b).length) return false;

@@ -8,0 +9,0 @@ for(var key in a) {

{
"name": "rich-text",
"version": "1.1.0",
"version": "2.0.0",
"description": "Format for representing rich text documents and changes.",

@@ -9,11 +9,11 @@ "author": "Jason Chen <jhchen7@gmail.com>",

"dependencies": {
"fast-diff": "~1.0.0"
"fast-diff": "~1.0.1"
},
"devDependencies": {
"chai": "~2.1.1",
"coveralls": "~2.11.1",
"chai": "~2.3.0",
"coveralls": "~2.11.2",
"grunt": "~0.4.5",
"istanbul": "~0.3.0",
"lodash": "~3.5.0",
"mocha": "~2.2.1",
"istanbul": "~0.3.14",
"lodash": "~3.9.3",
"mocha": "~2.2.5",
"ot-fuzzer": "~1.0.0"

@@ -20,0 +20,0 @@ },

@@ -39,3 +39,3 @@ # Rich Text [![Build Status](https://travis-ci.org/ottypes/rich-text.svg?branch=master)](http://travis-ci.org/ottypes/rich-text) [![Coverage Status](https://img.shields.io/coveralls/ottypes/rich-text.svg)](https://coveralls.io/r/ottypes/rich-text)

This format is suitable for [Operational Transform](https://en.wikipedia.org/wiki/Operational_transformation) and defines several functions to support this use case.
This format is suitable for [Operational Transform](https://en.wikipedia.org/wiki/Operational_transformation) and defines several functions ([`compose`](#compose), [`transform`](#transform), [`diff`](#diff)) to support this use case.

@@ -72,6 +72,4 @@ ## Contents

Insert operations have an `insert` key defined. A String value represents inserting text. A Number value represents inserting an embed, with the value corresponding to an embed type (such as an image or video).
Insert operations have an `insert` key defined. A String value represents inserting text. Any other type represents inserting an embed (however only one level of object comparison will be performed for equality).
Here we will use 1 to represent images and 2 to represent videos, but your application can choose whatever mapping is convenient.
In both cases of text and embeds, an optional `attributes` key can be defined with an Object to describe additonal formatting information. Formats can be changed by the [retain](#retain) operation.

@@ -86,16 +84,12 @@

// Insert an image
// Insert an embed
{
insert: 1,
attributes: {
alt: "Lab Octocat",
src: 'https://octodex.github.com/images/labtocat.png'
}
insert: { image: 'https://octodex.github.com/images/labtocat.png' },
attributes: { alt: "Lab Octocat" }
}
// Insert a video
// Insert another embed
{
insert: 2,
insert: { video: 'https://www.youtube.com/watch?v=dMH0bHeiRNg' },
attributes: {
src: "https://www.youtube.com/watch?v=dMH0bHeiRNg",
width: 420,

@@ -138,6 +132,4 @@ height: 315

A Delta is made up of an array of operations. Unless otherwise specified all methods are self modifying and return `this` for chainability.
A Delta is made up of an array of operations. All methods maintain the property that Deltas are represented in the most compact form. For example two consecutive insert operations of plain text will be merged into one. Thus a vanilla deep Object/Array comparison can be used to determine Delta equality.
All methods also maintain the property that Deltas are represented in the most compact form. For example two consecutive insert operations of plain text will be merged into one.
---

@@ -181,3 +173,3 @@

Appends an insert operation.
Appends an insert operation. Returns `this` for chainability.

@@ -206,3 +198,3 @@ #### Methods

Appends a delete operation.
Appends a delete operation. Returns `this` for chainability.

@@ -227,3 +219,3 @@ #### Methods

Appends a retain operation.
Appends a retain operation. Returns `this` for chainability.

@@ -249,3 +241,3 @@ #### Methods

Returns length of Delta.
Returns length of a Delta, which is the sum of the lengths of its operations.

@@ -305,3 +297,3 @@ #### Methods

Compose with another Delta, i.e. merge the operations of another Delta. This method is self modifying.
Returns a Delta that is equivalent to applying the operations of own Delta, followed by another Delta.

@@ -322,3 +314,4 @@ #### Methods

a.compose(b); // a == new Delta().insert('ac');
var composed = a.compose(b); // composed == new Delta().insert('ac');
```

@@ -391,3 +384,3 @@

Calculates the difference between two documents expressed as a Delta.
Returns a Delta representing the difference between two documents.

@@ -413,23 +406,4 @@ #### Methods

var diff = a.diff(b); // { ops: [{ retain: 5 }, { insert: '!' }] }
```
// a.compose(diff) == b
---
### length()
Calculates the length of the document.
#### Methods
- `length()`
#### Returns
- `Number` - length of the document
#### Example
```js
var delta = new Delta().insert('Hello');
var length = delta.length();
```

@@ -66,2 +66,10 @@ var Delta = require('../../lib/delta');

it('insert(embed) non-integer', function () {
var embed = { url: 'http://quilljs.com' };
var attr = { alt: 'Quill' };
var delta = new Delta().insert(embed, attr);
expect(delta.ops.length).to.equal(1);
expect(delta.ops[0]).to.deep.equal({ insert: embed, attributes: attr });
});
it('insert(text, attributes)', function () {

@@ -91,2 +99,8 @@ var delta = new Delta().insert('test', { bold: true });

it('insert(text) after delete no merge', function () {
var delta = new Delta().insert(1).delete(1).insert('a');
var expected = new Delta().insert(1).insert('a').delete(1);
expect(delta).to.deep.equal(expected);
});
it('insert(text, {})', function () {

@@ -185,6 +199,7 @@ var delta = new Delta().insert('a', {});

it('push(op) consecutive embeds with matching attributes', function () {
var delta = new Delta().insert({ url: 'http://quilljs.com' });
delta.push({ attributes: { url: 'http://quilljs.com' } });
var delta = new Delta().insert(1, { alt: 'Description' });
delta.push({ insert: { url: 'http://quilljs.com' }, attributes: { alt: 'Description' } });
console.log(JSON.stringify(delta))
expect(delta.ops.length).to.equal(2);
});
});

@@ -127,2 +127,16 @@ var Delta = require('../../lib/delta');

});
it('immutability', function () {
var attr1 = { bold: true };
var attr2 = { bold: true };
var a1 = new Delta().insert('Test', attr1);
var a2 = new Delta().insert('Test', attr1);
var b1 = new Delta().retain(1, { color: 'red' }).delete(2);
var b2 = new Delta().retain(1, { color: 'red' }).delete(2);
var expected = new Delta().insert('T', { color: 'red', bold: true }).insert('t', attr1);
expect(a1.compose(b1)).to.deep.equal(expected);
expect(a1).to.deep.equal(a2);
expect(b1).to.deep.equal(b2);
expect(attr1).to.deep.equal(attr2);
});
});

@@ -34,3 +34,3 @@ var Delta = require('../../lib/delta');

it('embed match', function () {
it('embed integer match', function () {
var a = new Delta().insert(1);

@@ -42,2 +42,23 @@ var b = new Delta().insert(1);

it('embed integer mismatch', function () {
var a = new Delta().insert(1);
var b = new Delta().insert(2);
var expected = new Delta().delete(1).insert(2);
expect(a.diff(b)).to.deep.equal(expected);
});
it('embed object match', function () {
var a = new Delta().insert({ image: 'http://quilljs.com' });
var b = new Delta().insert({ image: 'http://quilljs.com' });
var expected = new Delta();
expect(a.diff(b)).to.deep.equal(expected);
});
it('embed object mismatch', function () {
var a = new Delta().insert({ image: 'http://quilljs.com', alt: 'Overwrite' });
var b = new Delta().insert({ image: 'http://quilljs.com' });
var expected = new Delta().insert({ image: 'http://quilljs.com' }).delete(1);
expect(a.diff(b)).to.deep.equal(expected);
});
it('embed false positive', function () {

@@ -74,2 +95,22 @@ var a = new Delta().insert(1);

});
it('same document', function () {
var a = new Delta().insert('A').insert('B', { bold: true });
expected = new Delta();
expect(a.diff(a)).to.deep.equal(expected);
});
it('immutability', function () {
var attr1 = { color: 'red' };
var attr2 = { color: 'red' };
var a1 = new Delta().insert('A', attr1);
var a2 = new Delta().insert('A', attr1);
var b1 = new Delta().insert('A', { bold: true }).insert('B');
var b2 = new Delta().insert('A', { bold: true }).insert('B');
var expected = new Delta().retain(1, { bold: true, color: null }).insert('B');
expect(a1.diff(b1)).to.deep.equal(expected);
expect(a1).to.deep.equal(a2);
expect(b2).to.deep.equal(b2);
expect(attr1).to.deep.equal(attr2);
});
});

@@ -131,2 +131,13 @@ var Delta = require('../../lib/delta');

});
it('immutability', function () {
var a1 = new Delta().insert('A');
var a2 = new Delta().insert('A');
var b1 = new Delta().insert('B');
var b2 = new Delta().insert('B');
var expected = new Delta().retain(1).insert('B');
expect(a1.transform(b1, true)).to.deep.equal(expected);
expect(a1).to.deep.equal(a2);
expect(b1).to.deep.equal(b2);
});
});

@@ -13,2 +13,10 @@ var _ = require('lodash');

function generateRandomEmbed () {
switch(fuzzer.randomInt(4)) {
case 0: return 1;
case 1: return 2;
case 2: return { image: 'http://quilljs.com' };
case 3: return { url: 'http://quilljs.com' };
}
};

@@ -71,3 +79,3 @@ function generateRandomFormat (includeNull) {

// Insert embed
var type = fuzzer.randomInt(2) + 1;
var type = generateRandomEmbed();
var formats = generateRandomFormat(false);

@@ -74,0 +82,0 @@ delta.insert(type, formats);

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc