Skip to content

Proposal for a new Automerge.TextSpan type #239

Open
@nornagon

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions