|
- import { asArray, asSingleValue } from './multiplicity-utils.js';
- /**
- * Turn a partial annotation into a ‘well-formed’ WebAnnotation.
- *
- * It sets the following properties, if absent in the given stub:
- * - `@context` as required
- * - `type` as required, to `'Annotation'`
- * - `created` as recommended (to the current time)
- * - `target` to `'about:invalid'`
- *
- * @returns A shallow clone of the given annotation stub, with the missing
- * properties added.
- */
- export function completeAnnotationStub(annotationStub) {
- const webAnnotation = Object.assign({ '@context': 'http://www.w3.org/ns/anno.jsonld', type: 'Annotation', created: new Date().toISOString(), id: '', target: 'about:invalid' }, annotationStub);
- return webAnnotation;
- }
- /**
- * Get the name of the creator. If there are multiple, returns the first.
- * Assumes the creator is a nested Agent object: if the creator a string
- * (presumably the URL of an Agent node), `undefined` is returned.
- */
- export function getSingleCreatorName(annotationOrBody) {
- var _a;
- const creator = asSingleValue(annotationOrBody.creator);
- if (typeof creator === 'string')
- return undefined;
- return asSingleValue((_a = creator === null || creator === void 0 ? void 0 : creator.name) !== null && _a !== void 0 ? _a : creator === null || creator === void 0 ? void 0 : creator.nickname);
- }
- /**
- * Check whether the annotation likely targets the given URL.
- *
- * The word “likely” is used because, in its comparison, this ignores the URL
- * scheme, fragment and query parameters.
- *
- * Note that, strictly speaking, a URL should be treated as an opaque string.
- * In practice, it may however be useful to consider URLs as ‘likely equivalent’
- * in order to apply annotations targeting one URL to the document with the
- * very similar URL. Apply with caution: Especially a different query may,
- * depending on the website at hand, result in very different documents.
- */
- export function targetsUrl(target, url) {
- return getTargetUrls(target).some((targetUrl) => sameishUrl(targetUrl, url));
- }
- // Compare URLs while ignoring the scheme, fragment identifier, query parameter and trailing slash.
- function sameishUrl(url1, url2) {
- return normaliseUrl(url1) === normaliseUrl(url2);
- }
- function normaliseUrl(url) {
- url = url
- .split('#')[0]
- .split('?')[0]
- .replace(/^[a-zA-Z0-9.+-]+:\/\//, '');
- if (url.endsWith('/'))
- url = url.slice(0, -1);
- return url;
- }
- /**
- * Get the URLs of the resources that the annotation targets, for all its
- * targets.
- */
- export function getTargetUrls(target) {
- return unique(asArray(target).map(getTargetUrl));
- }
- /**
- * Get the URL of the resource that the annotation targets, for a single
- * target.
- */
- export function getTargetUrl(target) {
- if (typeof target === 'string') {
- // This string *could* be referring to a non-nested SpecificResource that
- // then contains the actual target URL. But we are not able to fetch that
- // now, and simply assume the string refers to the target document.
- return target;
- }
- // Specific Resource
- if ('source' in target)
- return target.source;
- // External Resource
- return target.id;
- }
- /**
- * Get the exact quotes that the annotation targets using a TextQuoteSelector,
- * if any.
- */
- export function getTargetQuotes(target) {
- const quotes = unique(asArray(target).map(getTargetQuote)).filter((s) => s !== undefined);
- return quotes;
- }
- /**
- * Get the exact quote that a single target of an annotation targets using a
- * TextQuoteSelector, if any.
- */
- export function getTargetQuote(target) {
- if (typeof target === 'string')
- return undefined;
- if ('selector' in target) {
- // Find if target.selector is/has a TextQuoteSelector.
- const selectors = asArray(target.selector);
- const textQuoteSelector = selectors.find(selector => {
- if (typeof selector === 'string') {
- // The selector is not nested in the annotation. But we are not able to
- // fetch it now, and will thus have to ignore this selector.
- return false;
- }
- return selector.type === 'TextQuoteSelector';
- });
- if (textQuoteSelector)
- return textQuoteSelector.exact;
- }
- }
- function unique(a) {
- return [...new Set(a)];
- }
|