Delta

https://travis-ci.org/quilljs/delta.svg?branch=masterBuild Status https://img.shields.io/coveralls/quilljs/delta.svgCoverage Status

Deltas是一种简单但富有表现力的格式,可用于描述内容和变化。 格式基于JSON,是人类可读的,但很容易被机器解析。 Deltas可以描述任何富文本文档,包括所有文本和格式信息,而不会产生HTML的模糊性和复杂性。

Delta由一组操作组成,用于描述文档的更改。 它们可以是插入,删除或保留。 注意操作不带索引。 他们总是描述当前指数的变化。使用保留来“保持”或“跳过”文档的某些部分。

不要被其名称混淆Delta-Deltas代表文档和文档更改。如果您将Deltas视为从一个文档转到另一个文档的指令,则Deltas表示文档的方式是从空文档开始表达指令。

快速示例

// Document with text "Gandalf the Grey"
// with "Gandalf" bolded, and "Grey" in grey
const delta = new Delta([
  { insert: 'Gandalf', attributes: { bold: true } },
  { insert: ' the ' },
  { insert: 'Grey', attributes: { color: '#ccc' } },
]);

// Change intended to be applied to above:
// Keep the first 12 characters, delete the next 4,
// and insert a white 'White'
const death = new Delta()
  .retain(12)
  .delete(4)
  .insert('White', { color: '#fff' });
// {
//   ops: [
//     { retain: 12 },
//     { delete: 4 },
//     { insert: 'White', attributes: { color: '#fff' } }
//   ]
// }

// Applying the above:
const restored = delta.compose(death);
// {
//   ops: [
//     { insert: 'Gandalf ', attributes: { bold: true } },
//     { insert: 'the ' },
//     { insert: 'White', attributes: { color: '#fff' } }
//   ]
// }

本自述文件以其一般形式和API功能描述了Deltas。 关于Quill特别使用Deltas的方式的其他信息可以在其自己的Delta文档中找到。Deltas背后的动机和设计思想的演练是设计Delta格式。

此格式适用于Operational Transform,并定义了几个函数来支持此用例。

内容

文档

调用或使用非文档Deltas的这些方法将导致未定义的行为。

操作

插入操作

插入操作定义了插入键。 String值表示插入文本。任何其他类型表示插入嵌入(但是只会执行一级对象比较以获得相等性)。

在文本和嵌入的两种情况下,可以使用Object定义可选属性键以描述附加格式信息。 可以通过retain操作更改格式。

// Insert a bolded "Text"
{ insert: "Text", attributes: { bold: true } }

// Insert a link
{ insert: "Google", attributes: { link: 'https://www.google.com' } }

// Insert an embed
{
  insert: { image: 'https://octodex.github.com/images/labtocat.png' },
  attributes: { alt: "Lab Octocat" }
}

// Insert another embed
{
  insert: { video: 'https://www.youtube.com/watch?v=dMH0bHeiRNg' },
  attributes: {
    width: 420,
    height: 315
  }
}

删除操作

删除操作定义了一个数字删除键,表示要删除的字符数。所有嵌入的长度均为1。

// Delete the next 10 characters
{ delete: 10 }

保留操作

保留操作定义了一个Number保留键,表示要保留的字符数(其他库可能使用名称keep或skip)。可以使用Object定义可选属性键,以描述对字符范围的格式更改。属性Object中的null值表示删除该键。

注意:没有必要保留文档的最后一个字符,因为这是隐含的。

// Keep the next 5 characters
{ retain: 5 }

// Keep and bold the next 5 characters
{ retain: 5, attributes: { bold: true } }

// Keep and unbold the next 5 characters
// More specifically, remove the bold key in the attributes Object
// in the next 5 characters
{ retain: 5, attributes: { bold: null } }

构造

constructor

创建一个新的Delta对象。

方法

  • new Delta()

  • new Delta(ops)

  • new Delta(delta)

参数

  • ops - 一系列操作

  • delta - 将ops键设置为操作数组的对象

注意:使用ops或delta构造时,不执行有效性/健全性检查。 新delta的内部ops数组也将从ops或delta.ops中分配,无需深度复制。

const delta = new Delta([
  { insert: 'Hello World' },
  { insert: '!', attributes: { bold: true } },
]);

const packet = JSON.stringify(delta);

const other = new Delta(JSON.parse(packet));

const chained = new Delta().insert('Hello World').insert('!', { bold: true });

insert()

附加插入操作。为可链接性返回此值。

方法

  • insert(text, attributes)

  • insert(embed, attributes)

参数

  • text - 表示要插入的文本的字符串

  • embed - 表示要插入的嵌入类型的对象

  • attributes - 要应用的可选属性

delta.insert('Text', { bold: true, color: '#ccc' });
delta.insert({ image: 'https://octodex.github.com/images/labtocat.png' });

delete()

附加删除操作。为可链接性返回此值。

方法

  • delete(length)

参数

  • length - 要删除的字符数

delta.delete(5);

retain()

附加保留操作。为可链接性返回此值。

方法

  • retain(length, attributes)

参数

  • length -要保留的字符数

  • attributes - 要应用的可选属性

delta.retain(4).retain(5, { color: '#0c6' });

文档

concat()

返回一个新Delta,表示此和另一个文档Delta的操作的串联。

方法

  • concat(other)

参数

  • other - 文档Delta连接

Returns

  • Delta - 连锁文件Delta

const a = new Delta().insert('Hello');
const b = new Delta().insert('!', { bold: true });

// {
//   ops: [
//     { insert: 'Hello' },
//     { insert: '!', attributes: { bold: true } }
//   ]
// }
const concat = a.concat(b);

diff()

返回表示两个文档之间差异的De​​lta。 (可选)接受发生更改的建议索引,通常表示更改前的光标位置。

方法

  • diff(other)

  • diff(other, index)

参数

  • other - 记录Delta以对抗差异

  • index - 建议的变更发生的指数

Returns

  • Delta - 两个文件之间的区别

const a = new Delta().insert('Hello');
const b = new Delta().insert('Hello!');

const diff = a.diff(b); // { ops: [{ retain: 5 }, { insert: '!' }] }
// a.compose(diff) == b

eachLine()

迭代文档Delta,使用Delta和属性对象调用给定函数,表示线段。

方法

  • eachLine(predicate, newline)

参数

  • predicate - 调用每个线组的函数

  • newline - 换行符,默认为 n

const delta = new Delta()
  .insert('Hello\n\n')
  .insert('World')
  .insert({ image: 'octocat.png' })
  .insert('\n', { align: 'right' })
  .insert('!');

delta.eachLine((line, attributes, i) => {
  console.log(line, attributes, i);
  // Can return false to exit loop early
});
// Should log:
// { ops: [{ insert: 'Hello' }] }, {}, 0
// { ops: [] }, {}, 1
// { ops: [{ insert: 'World' }, { insert: { image: 'octocat.png' } }] }, { align: 'right' }, 2
// { ops: [{ insert: '!' }] }, {}, 3

invert()

返回一个倒三角形,它对基础文档增量具有相反的效果。 那是base.compose(delta).compose(inverted) === base.

方法

  • invert(base)

参数

  • base - 记录delta反转

Returns

  • Delta - 倒三角形对基三角洲

const base = new Delta().insert('Hello\n').insert('World');
const delta = new Delta()
  .retain(6, { bold: true })
  .delete(5)
  .insert('!');

const inverted = delta.invert(base); // { ops: [
//   { retain: 6, attributes: { bold: null } },
//   { insert: 'World' },
//   { delete: 1 }
// ]}
// base.compose(delta).compose(inverted) === base

效用

filter()

返回传递给定函数的操作数组。

方法

  • filter(predicate)

参数

  • predicate - 用于测试每个操作的功能。返回true表示保持操作,否则返回false。

Returns

  • Array - 过滤后的结果数组

const delta = new Delta()
  .insert('Hello', { bold: true })
  .insert({ image: 'https://octodex.github.com/images/labtocat.png' })
  .insert('World!');

const text = delta
  .filter(op => typeof op.insert === 'string')
  .map(op => op.insert)
  .join('');

forEach()

迭代操作,为每个操作调用提供的函数。

方法

  • forEach(predicate)

参数

  • predicate - 函数在迭代期间调用,传入当前操作。

delta.forEach(op => {
  console.log(op);
});

length()

返回Delta的长度,它是其操作长度的总和。

方法

  • length()

new Delta().insert('Hello').length(); // Returns 5

new Delta()
  .insert('A')
  .retain(2)
  .delete(1); // Returns 4

map()

返回一个新数组,其中包含在每个操作上调用提供函数的结果。

方法

  • map(predicate)

参数

  • predicate - 函数调用,传入当前操作,返回要返回的新数组的元素

Returns

  • Array - 一个新数组,每个元素都是给定函数的结果。

const delta = new Delta()
  .insert('Hello', { bold: true })
  .insert({ image: 'https://octodex.github.com/images/labtocat.png' })
  .insert('World!');

const text = delta
  .map(op => {
    if (typeof op.insert === 'string') {
      return op.insert;
    } else {
      return '';
    }
  })
  .join('');

partition()

创建一个包含两个数组的数组,第一个数组包含传递给定函数的操作,另一个数组失败。

方法

  • partition(predicate)

参数

  • predicate - 函数调用,传入当前操作,返回该操作是否通过

Returns

  • Array - 一个包含两个Arrays的新数组,第一个带有传递的操作,另一个带有失败的操作

const delta = new Delta()
  .insert('Hello', { bold: true })
  .insert({ image: 'https://octodex.github.com/images/labtocat.png' })
  .insert('World!');

const results = delta.partition(op => typeof op.insert === 'string');
const passed = results[0]; // [{ insert: 'Hello', attributes: { bold: true }},
//  { insert: 'World'}]
const failed = results[1]; // [{ insert: { image: 'https://octodex.github.com/images/labtocat.png' }}]

reduce()

对累加器应用给定函数,并将每个操作减少为单个值。

方法

  • reduce(predicate, initialValue)

参数

  • predicate - 每次迭代调用的函数,返回累计值

  • initialValue - 传递给第一次调用谓词的初始值

Returns

  • any - 累计值

const delta = new Delta().insert('Hello', { bold: true })
                         .insert({ image: 'https://octodex.github.com/images/labtocat.png' })
                         .insert('World!');

const length = delta.reduce((length, op) => (
  length + (op.insert.length || 1);
), 0);

slice()

返回带有操作子集的delta副本。

方法

  • slice()

  • slice(start)

  • slice(start, end)

参数

  • start - 启动子集索引,默认为0

  • end - 子集的结束索引,默认为其余操作

const delta = new Delta().insert('Hello', { bold: true }).insert(' World');

// {
//   ops: [
//     { insert: 'Hello', attributes: { bold: true } },
//     { insert: ' World' }
//   ]
// }
const copy = delta.slice();

// { ops: [{ insert: 'World' }] }
const world = delta.slice(6);

// { ops: [{ insert: ' ' }] }
const space = delta.slice(5, 6);

运营转型

compose()

返回一个Delta,相当于应用自己Delta的操作,然后是另一个Delta。

方法

  • compose(other)

参数

  • other - 三角洲组成

const a = new Delta().insert('abc');
const b = new Delta().retain(1).delete(1);

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

transform()

根据自己的运营改变Delta。

方法

  • transform(other, priority = false)

  • transform(index, priority = false) - transformPosition的别名

参数

  • other - Delta to transform

  • priority - 用于打破关系的布尔值。如果为true,那么这优先于其他,也就是说,它的行为被认为是“第一次”。

Returns

  • Delta - transformed Delta

const a = new Delta().insert('a');
const b = new Delta()
  .insert('b')
  .retain(5)
  .insert('c');

a.transform(b, true); // new Delta().retain(1).insert('b').retain(5).insert('c');
a.transform(b, false); // new Delta().insert('b').retain(6).insert('c');

transformPosition()

根据delta转换索引。用于表示光标/选择位置。

方法

  • transformPosition(index, priority = false)

参数

  • index - 变换的索引

Returns

  • Number - 转化指数

const delta = new Delta().retain(5).insert('a');
delta.transformPosition(4); // 4
delta.transformPosition(5); // 6