From 46b5896adb47258ec56953bd3594990e406d8706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFs=20Poujade?= <lois.poujade@tetras-libre.fr> Date: Tue, 20 Dec 2022 15:00:54 +0100 Subject: [PATCH] Separate xywh & time fragment selectors handle both fragment selectors types: - target: https://ressource.url#xywh=0,0,10,10&t=19,20 - target: https..., selectors: [ FragmentSelector: ..., ] --- __tests__/WebAnnotation.test.js | 28 ++++++++++++++++++----- src/AnnotationCreation.js | 26 ++++++++++------------ src/WebAnnotation.js | 39 +++++++++++++++++---------------- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/__tests__/WebAnnotation.test.js b/__tests__/WebAnnotation.test.js index 80ace4d..1b0cb50 100644 --- a/__tests__/WebAnnotation.test.js +++ b/__tests__/WebAnnotation.test.js @@ -8,6 +8,7 @@ function createSubject(args = {}) { id: 'id', svg: 'svg', tags: ['tags'], + timing: [1, 3], xywh: 'xywh', ...args, }); @@ -20,26 +21,31 @@ describe('WebAnnotation', () => { ['body', 'canvasId', 'id', 'svg', 'xywh'].forEach((prop) => { expect(subject[prop]).toBe(prop); }); + expect(subject.timing).toStrictEqual([1, 3]); }); }); describe('target', () => { - it('with svg and xywh', () => { + it('with svg, xywh and timing', () => { expect(subject.target()).toEqual({ selector: [ + { + type: 'SvgSelector', + value: 'svg', + }, { type: 'FragmentSelector', value: 'xywh=xywh', }, { - type: 'SvgSelector', - value: 'svg', + type: 'FragmentSelector', + value: 't=1,3', }, ], source: 'canvasId', }); }); it('with svg only', () => { - subject = createSubject({ xywh: null }); + subject = createSubject({ timing: null, xywh: null }); expect(subject.target()).toEqual({ selector: { type: 'SvgSelector', @@ -49,7 +55,7 @@ describe('WebAnnotation', () => { }); }); it('with xywh only', () => { - subject = createSubject({ svg: null }); + subject = createSubject({ svg: null, timing: null }); expect(subject.target()).toEqual({ selector: { type: 'FragmentSelector', @@ -58,8 +64,18 @@ describe('WebAnnotation', () => { source: 'canvasId', }); }); - it('with no xywh or svg', () => { + it('with timing only', () => { subject = createSubject({ svg: null, xywh: null }); + expect(subject.target()).toEqual({ + selector: { + type: 'FragmentSelector', + value: 't=1,3', + }, + source: 'canvasId', + }); + }); + it('with no xywh, svg or timing', () => { + subject = createSubject({ svg: null, timing: null, xywh: null }); expect(subject.target()).toBe('canvasId'); }); }); diff --git a/src/AnnotationCreation.js b/src/AnnotationCreation.js index 4b5a275..6bb0b42 100644 --- a/src/AnnotationCreation.js +++ b/src/AnnotationCreation.js @@ -33,8 +33,9 @@ import CursorIcon from './icons/Cursor'; /** Extract time information from annotation target */ function timeFromAnnoTarget(annotarget) { + console.info('TODO proper time extraction from: ', annotarget); // TODO w3c media fragments: t=,10 t=5, - const r = /t=([0-9]+),([0-9]+)/.exec(annotarget); + const r = /t=([0-9.]+),([0-9.]+)/.exec(annotarget); if (!r || r.length !== 3) { return ['', '']; } @@ -43,13 +44,12 @@ function timeFromAnnoTarget(annotarget) { /** Extract xywh from annotation target */ function geomFromAnnoTarget(annotarget) { - console.warn('TODO proper extraction'); + console.info('TODO proper xywh extraction from: ', annotarget); const r = /xywh=((-?[0-9]+,?)+)/.exec(annotarget); - console.info('extracted from ', annotarget, r); if (!r || r.length !== 3) { - return ['', '']; + return ''; } - return [r[1], r[2]]; + return r[1]; } /** */ @@ -88,12 +88,12 @@ class AnnotationCreation extends Component { }); } else { annoState.svg = props.annotation.target.selector.value; - // eslint-disable-next-line max-len - [annoState.tstart, annoState.tend] = timeFromAnnoTarget(props.annotation.target.selector.value); + // TODO does this happen ? when ? where are fragments selectors ? } + } else if (typeof props.annotation.target === 'string') { + annoState.xywh = geomFromAnnoTarget(props.annotation.target); + [annoState.tstart, annoState.tend] = timeFromAnnoTarget(props.annotation.target); } - // - // start/end time } const toolState = { @@ -196,10 +196,7 @@ class AnnotationCreation extends Component { const { annoBody, tags, xywh, svg, tstart, tend, textEditorStateBustingKey, } = this.state; - let fsel = xywh; - if (tstart && tend) { - fsel = `${xywh || ''}&t=${tstart},${tend}`; - } + const timing = (tstart && tend) ? [tstart, tend] : null; canvases.forEach((canvas) => { const storageAdapter = config.annotation.adapter(canvas.id); const anno = new WebAnnotation({ @@ -209,7 +206,8 @@ class AnnotationCreation extends Component { manifestId: canvas.options.resource.id, svg, tags, - xywh: fsel, + timing, + xywh, }).toJson(); if (annotation) { storageAdapter.update(anno).then((annoPage) => { diff --git a/src/WebAnnotation.js b/src/WebAnnotation.js index 22bff18..d31c22b 100644 --- a/src/WebAnnotation.js +++ b/src/WebAnnotation.js @@ -2,11 +2,12 @@ export default class WebAnnotation { /** */ constructor({ - canvasId, id, xywh, body, tags, svg, manifestId, + canvasId, id, xywh, timing, body, tags, svg, manifestId, }) { this.id = id; this.canvasId = canvasId; this.xywh = xywh; + this.timing = timing; this.body = body; this.tags = tags; this.svg = svg; @@ -48,33 +49,33 @@ export default class WebAnnotation { /** */ target() { - let target = this.canvasId; - if (this.svg || this.xywh) { - target = { - source: this.source(), - }; + if (!this.svg && !this.xywh && !this.timing) { + return this.canvasId; } + const selectors = []; + const target = { + source: this.source(), + }; if (this.svg) { - target.selector = { + selectors.push({ type: 'SvgSelector', value: this.svg, - }; + }); } if (this.xywh) { - const fragsel = { + selectors.push({ type: 'FragmentSelector', value: `xywh=${this.xywh}`, - }; - if (target.selector) { - // add fragment selector - target.selector = [ - fragsel, - target.selector, - ]; - } else { - target.selector = fragsel; - } + }); + } + if (this.timing) { + const [start, end] = this.timing; + selectors.push({ + type: 'FragmentSelector', + value: `t=${start},${end}`, + }); } + target.selector = selectors.length === 1 ? selectors[0] : selectors; return target; } -- GitLab