recogito-client-core/src/WebAnnotation.js

120 lines
2.9 KiB
JavaScript

import { v4 as uuid } from 'uuid';
import * as equals from 'fast-deep-equal';
export default class WebAnnotation {
constructor(annotation, opts) {
this.underlying = annotation;
this.opts = opts;
}
/** For convenience - creates an empty web annotation **/
static create = args => {
const stub = {
'@context': 'http://www.w3.org/ns/anno.jsonld',
'type': 'Annotation',
'id': `#${uuid()}`,
'body': []
};
return new WebAnnotation({ ...stub, ...args });
}
/** Creates a copy of this annotation **/
clone = opt_props => {
return new WebAnnotation({ ...this.underlying, ...opt_props}, this.opts);
}
/** An equality check based on the underlying object **/
isEqual(other) {
if (other?.type !== 'Annotation') {
return false;
} else if (this.underlying === other.underlying) {
return true;
} else if (!this.underlying.id || !other.underlying.id) {
return false;
} else {
return equals(this.underlying, other.underlying);
}
}
get readOnly() {
return this.opts?.readOnly;
}
/*************************************/
/* Getters to forward properties of */
/* the underlying annotation */
/*************************************/
get id() {
return this.underlying.id;
}
get type() {
return this.underlying.type;
}
get motivation() {
return this.underlying.motivation;
}
get body() {
return this.underlying.body;
}
get target() {
return this.underlying.target;
}
/** Same as .body, but guaranteed to return an array **/
get bodies() {
return (Array.isArray(this.underlying.body)) ?
this.underlying.body : [ this.underlying.body ];
}
/** Only bodies are meant to be mutated by the application **/
set bodies(bodies) {
this.underlying.body = bodies;
}
/** Same as .target, but guaranteed to return an array **/
get targets() {
return (Array.isArray(this.underlying.target)) ?
this.underlying.target : [ this.underlying.target ];
}
/*****************************************/
/* Various access helpers and shorthands */
/*****************************************/
/** Selector of the given type **/
selector = type => {
const { target } = this.underlying;
if (target.selector) {
// Normalize to array
const selectors = Array.isArray(target.selector) ?
target.selector : [ target.selector ];
return selectors.find(s => s.type === type);
}
}
/** Shorthand for the 'exact' field of the TextQuoteSelector **/
get quote() {
return this.selector('TextQuoteSelector').exact;
}
/** Shorthand for the 'start' field of the TextPositionSelector **/
get start() {
return this.selector('TextPositionSelector').start;
}
/** Shorthand for the 'end' field of the TextPositionSelector **/
get end() {
return this.selector('TextPositionSelector').end;
}
}