Description
In order to support the Ordered Array of Formatting Spans (OAFS) model for Rich Text, it's necessary to maintain a list of references into an Automerge.Text object, along with the formatting attributes to be applied to the given range. For illustration, consider represent the string "Gandalf the Grey", where the string "Gandalf" is bold:
{
"text": "Gandalf the Grey",
"attributes": [
{ "from": 0, "to": 7, "attributes": { "bold": true } }
]
}
However, in order to make sure the references remain consistent across operations, instead of using index references, one should store the ID of the referenced character. IDs for individual characters are not currently exposed by Automerge, and further, IDs would need to be translated back to string offsets in order to be meaningful to a client.
Spans would also be useful for representing and transforming user cursors/selections.
API
Creating a TextSpan would be done from the corresponding Text object:
const text = new Automerge.Text('Gandalf the Grey')
const span = text.getSpan(0, 7)
Spans are Automerge objects, so they can be stored in a document:
const doc = Automerge.from({
text: new Automerge.Text('Gandalf the Grey'),
attributes: []
})
doc.change(d => {
const span = d.text.getSpan(0, 7)
d.attributes.push({ span, attributes: { bold: true } })
})
Spans can be inspected, and have "start" and "end" properties that are the calculated offsets into the Text object which they reference:
doc.attributes[0].start === 0
doc.attributes[0].end === 7
When the associated Text has characters inserted or removed, Span objects will stay up-to-date:
const text = new Automerge.Text('Gandalf the Grey')
const doc = Automerge.from({
text,
span: text.span(0, 7)
})
const doc2 = doc.change(d => {
d.text.insertAt(3, 'non')
})
doc2.span.end === 10
Activity