3.7 KiB
3.7 KiB
Deltas
- Enable you to efficiently represent changes on all kinds of data structures.
- Support schemas
- Support OT-style conflict resolution
delta2.apply(delta1.rebase(delta2, true)) === delta1.apply(delta2.rebase(delta1, false)) - nice typings
Delta for Map-like structures
// define schema
const $d = delta.$delta(s.$any, { attr1: s.$string, attr2: s.$number })
const d = delta.create($d)
// create an update
const update = delta.create().set('attr1', 'val1').set('attr2', 42)
d.apply(update)
// In case of an invalid update
const update2 = delta.create().set('attr1', 42)
// it is possible to check an update beforehand
$d.check(update2) // => false
// and you also get type errors
d.apply(update2) // type error: expected 'attr1' to be of type string
Delta for Text-like structures
Text-like deltas work similarly to [Quill Deltas]{https://quilljs.com/docs/delta}
// define schema
const $d = delta.$delta(s.$any, null, s.$string)
const d = delta.create($d).insert('hello world')
// create an update
const update = delta.create().retain(11).insert('!')
d.apply(update)
// In case of an invalid update
const update2 = delta.create().insert([{ some: 'object' }])
// it is possible to check an update beforehando
$d.check(update2) // => false
// and you also get type errors
d.apply(update2) // type error: unexpected attribute 'attr1'
Delta for Array-like structures
// define schema
const $d = delta.$delta(s.$any, null, s.$array(s.object({ some: s.$string }, s.$string)))
const d = delta.create($d).insert(['hello world'])
// create an update
const update = delta.create().retain(1).insert({ some: 'object' })
d.apply(update)
// In case of an invalid update
const update2 = delta.create().insert([{ unknown: 'prop' }])
// it is possible to check an update beforehando
$d.check(update2) // => false
// and you also get type errors
d.apply(update2) // type error: { unknown: 'prop' } is not assignable to { some: string }
Delta for Node-like structures (similar to XML,Trees with named nodes)
// define schema for a 'p'|'h1' node that may contain text or other instances of itself
const $d = delta.$delta(s.$literal('div', 'p', 'h1'), { style: s.$string }, s.$string, true))
const d = delta.create('div', $d)
// create an update - insert paragraph into the <div>
const update = delta.create().insert([delta.create('p', { style: 'bold: true' }, 'hello world')])
d.apply(update)
// modify the paragraph by deleting the text 'world' and appending '!'
d.apply(delta.create().modify(
delta.create().retain(6).delete(5).insert('!')
))
Transformers
We often have two different data structures that we want to sync. There might be slight differences between those data structures. I.e. we might have a Yjs data structure containing the following content:
/**
* {
* headline: {{ headline }},
* content: {{ content }}
* }
*/
const $data = s.$delta(null, { headline: s.$string, content: s.$string })
A typical scenario is that we want to sync that to the dom and back. "two-way bindings"
- When the Yjs struucture updates, we want to sync the changes to the dom.
- When the dom is updated (because the dom is a
contenteditableeditor), we want to sync back the changes to the yjs structure.
Now, the dom might look like this:
/**
* <div>
* <h1 style='some custom style'>{{headline}}</h1>
* <span>dturianed</span>
* <p>{{content}}</p>
* </div>
*/
We can achieve automattic back-and-forth transformations with delta transformers:
const Λdata = Λ.transform($data, $d =>
Λ.delta('div', {}, [
Λ.delta('h1', { style: 'bold:true' }, [Λ.query('headline')($d)], []),
Λ.delta('p', null, [Λ.query('content')($d)])
])
)