Skip to content

Tombstoned attributes #627

Description

@tim-evans

Currently, when we're doing conversions, we have a big grab bag of attributes that are semi-messily put into the same property on the annotation— attributes.

We've encountered a bunch of issues doing so, where we've added properties that aren't meaningful to the output to the annotation for metrics purposes, which have caused some issues with determining annotation equality. (Side note: we're using canonical document equality to determine whether we can edit a document in our rich text editor)

Another issue that has come up a few times is a TypeScript issue where we are casting an attribute as any to get around the type system, because we're using one of these "grab bag" attributes.

The suggestion here is to add a graveyard / tombstoned attributes property to the Annotation class that will serve as a way to safely access these attributes. These attributes will not affect annotation equality (that is, if two annotations are identical except for their tombstoned attributes, they will be treated as if they were equal).

Proposal

Add a new property to annotations that is set on initialization of an annotation called $attributes. This will contain all attributes that are in a different "vendor space" than the current annotation. (This is the first pass of this feature, since doing this more correctly requires us to have a schema that we can directly read from in the code).

abstract class Annotation<Attributes = {}> {
  id: string;
  start: number;
  end: number;
  attributes: Attributes;
  $attributes: { [key: string]: unknown };
}

$attributes will be serialized as-is into JSON, resulting in a JSON object that look like: attributes & $attributes.

For example:

import HTMLSource from "@atjson/source-html";
import OffsetSource from "@atjson/offset-annotations";

let doc = HTMLSource
  .fromRaw(`<h1 style="text-align:center;">Guilt</h1>`)
  .convertTo(OffsetSource);

let [heading] = doc.annotations.where({ type: "-offset-heading" });
console.log(heading);
// Heading {
//   start: 0,
//   end: 41,
//   attributes: {},
//   $attributes: {
//     -html-style: "text-align:center;"
//   }
// }

Metadata

Metadata

Labels

🎉 FeatureA new feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions