@annotorious/annotorious 3.0.0-rc.30 → 3.0.0-rc.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,11 @@ import { ImageAnnotation } from '../core';
3
3
  import { W3CImageAnnotation } from './W3CImageAnnotation';
4
4
 
5
5
  export type W3CImageFormatAdapter = FormatAdapter<ImageAnnotation, W3CImageAnnotation>;
6
- export declare const W3CImageFormat: (source: string, invertY?: boolean) => W3CImageFormatAdapter;
7
- export declare const parseW3CImageAnnotation: (annotation: W3CAnnotation, invertY?: boolean) => ParseResult<ImageAnnotation>;
8
- export declare const serializeW3CImageAnnotation: (annotation: ImageAnnotation, source: string) => W3CImageAnnotation;
6
+ export interface W3CImageFormatAdapterOpts {
7
+ strict: boolean;
8
+ invertY: boolean;
9
+ }
10
+ export declare const W3CImageFormat: (source: string, opts?: W3CImageFormatAdapterOpts) => W3CImageFormatAdapter;
11
+ export declare const parseW3CImageAnnotation: (annotation: W3CAnnotation, opts: W3CImageFormatAdapterOpts) => ParseResult<ImageAnnotation>;
12
+ export declare const serializeW3CImageAnnotation: (annotation: ImageAnnotation, source: string, opts: W3CImageFormatAdapterOpts) => W3CImageAnnotation;
9
13
  //# sourceMappingURL=W3CImageFormatAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"W3CImageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../src/model/w3c/W3CImageFormatAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAKlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;AAEvF,eAAO,MAAM,cAAc,WACjB,MAAM,YACL,OAAO,KACf,qBASF,CAAA;AAED,eAAO,MAAM,uBAAuB,eACtB,aAAa,YAChB,OAAO,KACf,WAAW,CAAC,eAAe,CA2C7B,CAAA;AAED,eAAO,MAAM,2BAA2B,eAC1B,eAAe,UACnB,MAAM,KACb,kBAsCF,CAAA"}
1
+ {"version":3,"file":"W3CImageFormatAdapter.d.ts","sourceRoot":"","sources":["../../../src/model/w3c/W3CImageFormatAdapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,SAAS,CAAC;AAKlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;AAEvF,MAAM,WAAW,yBAAyB;IAExC,MAAM,EAAE,OAAO,CAAC;IAEhB,OAAO,EAAE,OAAO,CAAC;CAElB;AAED,eAAO,MAAM,cAAc,WACjB,MAAM,SACR,yBAAyB,KAC9B,qBASF,CAAA;AAED,eAAO,MAAM,uBAAuB,eACtB,aAAa,QACnB,yBAAyB,KAC9B,WAAW,CAAC,eAAe,CA0C7B,CAAA;AAED,eAAO,MAAM,2BAA2B,eAC1B,eAAe,UACnB,MAAM,QACR,yBAAyB,KAC9B,kBA8CF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"spatialTree.d.ts","sourceRoot":"","sources":["../../src/state/spatialTree.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEtD,UAAU,aAAa;IAErB,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,MAAM,EAAE,qBAAqB,CAAC;CAE/B;AAED,eAAO,MAAM,iBAAiB;;;eA+CV,MAAM,KAAK,MAAM,KAAG,qBAAqB,GAAG,SAAS;yBAqB3C,MAAM,KAAK,MAAM,SAAS,MAAM,UAAU,MAAM;qBAvDpD,qBAAqB;qBASrB,qBAAqB;mBAYvB,qBAAqB,EAAE,YAAW,OAAO;;uBALrC,qBAAqB,WAAW,qBAAqB;CA6DhF,CAAA"}
1
+ {"version":3,"file":"spatialTree.d.ts","sourceRoot":"","sources":["../../src/state/spatialTree.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEtD,UAAU,aAAa;IAErB,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE,MAAM,CAAC;IAEb,MAAM,EAAE,qBAAqB,CAAC;CAE/B;AAED,eAAO,MAAM,iBAAiB;;;eAqDV,MAAM,KAAK,MAAM,KAAG,qBAAqB,GAAG,SAAS;yBAqB3C,MAAM,KAAK,MAAM,SAAS,MAAM,UAAU,MAAM;qBA7DpD,qBAAqB;qBASrB,qBAAqB;mBAYvB,qBAAqB,EAAE,YAAW,OAAO;;uBALrC,qBAAqB,WAAW,qBAAqB;CAmEhF,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@annotorious/annotorious",
3
- "version": "3.0.0-rc.30",
3
+ "version": "3.0.0-rc.31",
4
4
  "description": "Add image annotation functionality to any web page with a few lines of JavaScript",
5
5
  "author": "Rainer Simon",
6
6
  "license": "BSD-3-Clause",
@@ -39,16 +39,16 @@
39
39
  "@sveltejs/vite-plugin-svelte": "^3.1.1",
40
40
  "@tsconfig/svelte": "^5.0.4",
41
41
  "@types/rbush": "^3.0.3",
42
- "jsdom": "^24.1.0",
42
+ "jsdom": "^24.1.1",
43
43
  "svelte": "^4.2.18",
44
- "svelte-preprocess": "^6.0.1",
45
- "typescript": "^5.5.2",
46
- "vite": "^5.3.1",
44
+ "svelte-preprocess": "^6.0.2",
45
+ "typescript": "5.5.3",
46
+ "vite": "^5.3.5",
47
47
  "vite-plugin-dts": "^3.9.1",
48
- "vitest": "^1.6.0"
48
+ "vitest": "^2.0.4"
49
49
  },
50
50
  "dependencies": {
51
- "@annotorious/core": "3.0.0-rc.30",
51
+ "@annotorious/core": "3.0.0-rc.31",
52
52
  "rbush": "^4.0.0",
53
53
  "uuid": "^10.0.0"
54
54
  }
@@ -1,5 +1,5 @@
1
1
  import type { SvelteComponent } from 'svelte';
2
- import { PointerSelectAction } from '@annotorious/core';
2
+ import { UserSelectAction } from '@annotorious/core';
3
3
  import type { Annotator, DrawingStyleExpression, Filter, User } from '@annotorious/core';
4
4
  import { createAnonymousGuest, createBaseAnnotator, createLifecycleObserver, createUndoStack } from '@annotorious/core';
5
5
  import { registerEditor } from './annotation/editors';
@@ -19,6 +19,8 @@ import './themes/light/index.css';
19
19
 
20
20
  export interface ImageAnnotator<E extends unknown = ImageAnnotation> extends Annotator<ImageAnnotation, E> {
21
21
 
22
+ element: HTMLDivElement;
23
+
22
24
  listDrawingTools(): string[];
23
25
 
24
26
  registerDrawingTool(name: string, tool: typeof SvelteComponent, opts?: DrawingToolOpts): void;
@@ -41,13 +43,14 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
41
43
  if (!image)
42
44
  throw 'Missing argument: image';
43
45
 
44
- const img = (typeof image === 'string' ?
45
- document.getElementById(image) : image) as HTMLImageElement | HTMLCanvasElement;
46
+ const img = (
47
+ typeof image === 'string' ? document.getElementById(image) : image
48
+ ) as HTMLImageElement | HTMLCanvasElement;
46
49
 
47
50
  const opts = fillDefaults<ImageAnnotation, E>(options, {
48
51
  drawingEnabled: true,
49
52
  drawingMode: 'drag',
50
- pointerSelectAction: PointerSelectAction.EDIT,
53
+ userSelectAction: UserSelectAction.EDIT,
51
54
  theme: 'light'
52
55
  });
53
56
 
@@ -62,7 +65,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
62
65
  );
63
66
 
64
67
  // We'll wrap the image in a container DIV.
65
- const container = document.createElement('DIV');
68
+ const container = document.createElement('DIV') as HTMLDivElement;
66
69
  container.style.position = 'relative';
67
70
  container.style.display = 'inline-block';
68
71
 
@@ -93,7 +96,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
93
96
  annotationLayer.$on('click', (evt: CustomEvent<SVGAnnotationLayerPointerEvent>) => {
94
97
  const { originalEvent, annotation } = evt.detail;
95
98
  if (annotation)
96
- selection.clickSelect(annotation.id, originalEvent);
99
+ selection.userSelect(annotation.id, originalEvent);
97
100
  else if (!selection.isEmpty())
98
101
  selection.clear();
99
102
  });
@@ -173,6 +176,7 @@ export const createImageAnnotator = <E extends unknown = ImageAnnotation>(
173
176
  setTheme,
174
177
  setUser,
175
178
  setVisible,
179
+ element: container,
176
180
  state
177
181
  }
178
182
 
@@ -1,4 +1,4 @@
1
- import type { Annotation, DrawingStyle, DrawingStyleExpression, FormatAdapter, PointerSelectAction } from '@annotorious/core';
1
+ import type { Annotation, DrawingStyleExpression, FormatAdapter, UserSelectActionExpression } from '@annotorious/core';
2
2
  import type { ImageAnnotation } from './model';
3
3
 
4
4
  export interface AnnotoriousOpts<I extends Annotation = ImageAnnotation, E extends unknown = ImageAnnotation> {
@@ -13,7 +13,7 @@ export interface AnnotoriousOpts<I extends Annotation = ImageAnnotation, E exten
13
13
  // 'drag': starts drawing on drag, single click always selects
14
14
  drawingMode?: DrawingMode;
15
15
 
16
- pointerSelectAction?: PointerSelectAction | ((a: I) => PointerSelectAction);
16
+ userSelectAction?: UserSelectActionExpression<I>;
17
17
 
18
18
  style?: DrawingStyleExpression<ImageAnnotation>;
19
19
 
@@ -28,17 +28,13 @@ export type Theme = 'dark' | 'light' | 'auto';
28
28
  export const fillDefaults = <I extends ImageAnnotation = ImageAnnotation, E extends unknown = ImageAnnotation> (
29
29
  opts: AnnotoriousOpts<I, E>,
30
30
  defaults: AnnotoriousOpts<I, E>
31
- ): AnnotoriousOpts<I, E> => {
32
-
33
- return {
34
- ...opts,
35
- drawingEnabled: opts.drawingEnabled === undefined ? defaults.drawingEnabled : opts.drawingEnabled,
36
- drawingMode: opts.drawingMode || defaults.drawingMode,
37
- pointerSelectAction: opts.pointerSelectAction || defaults.pointerSelectAction,
38
- theme: opts.theme || defaults.theme
39
- };
40
-
41
- };
31
+ ): AnnotoriousOpts<I, E> => ({
32
+ ...opts,
33
+ drawingEnabled: opts.drawingEnabled === undefined ? defaults.drawingEnabled : opts.drawingEnabled,
34
+ drawingMode: opts.drawingMode || defaults.drawingMode,
35
+ userSelectAction: opts.userSelectAction || defaults.userSelectAction,
36
+ theme: opts.theme || defaults.theme
37
+ });
42
38
 
43
39
 
44
40
 
@@ -9,7 +9,7 @@
9
9
  import { getTool, listDrawingTools, ToolMount } from './tools';
10
10
  import { enableResponsive } from './utils';
11
11
  import { createSVGTransform } from './Transform';
12
- import { addEventListeners } from './SVGAnnotationLayerPointerEvent';
12
+ import { addEventListeners, getSVGPoint } from './SVGAnnotationLayerPointerEvent';
13
13
  import type { SvelteImageAnnotatorState } from 'src/state';
14
14
  import type { DrawingMode } from 'src/AnnotoriousOpts';
15
15
 
@@ -40,7 +40,7 @@
40
40
  $: transform = createSVGTransform(svgEl);
41
41
 
42
42
  /** Selection tracking */
43
- const { selection, store } = state;
43
+ const { hover, selection, store } = state;
44
44
 
45
45
  $: ({ onPointerDown, onPointerUp } = addEventListeners(svgEl, store));
46
46
 
@@ -115,6 +115,19 @@
115
115
  });
116
116
  }
117
117
 
118
+ const onPointerMove = (evt: PointerEvent) => {
119
+ const { x, y } = getSVGPoint(evt, svgEl);
120
+
121
+ const hit = store.getAt(x, y);
122
+ if (hit) {
123
+ if ($hover !== hit.id) {
124
+ hover.set(hit.id);
125
+ }
126
+ } else {
127
+ hover.set(undefined);
128
+ }
129
+ }
130
+
118
131
  // To get around lack of TypeScript support in Svelte markup
119
132
  const getEditor = (shape: Shape): typeof SvelteComponent => _getEditor(shape)!;
120
133
  </script>
@@ -124,20 +137,31 @@
124
137
  class="a9s-annotationlayer"
125
138
  class:drawing={tool}
126
139
  class:hidden={!visible}
140
+ class:hover={$hover}
127
141
  on:pointerup={onPointerUp}
128
- on:pointerdown={onPointerDown}>
142
+ on:pointerdown={onPointerDown}
143
+ on:pointermove={onPointerMove}>
129
144
 
130
145
  <g>
131
146
  {#each $store as annotation}
132
147
  {#if !isEditable(annotation)}
133
148
  {@const selector = annotation.target.selector}
134
149
  {#key annotation.id}
135
- {#if (selector.type === ShapeType.ELLIPSE)}
136
- <Ellipse annotation={annotation} geom={selector.geometry} style={style} />
137
- {:else if (selector.type === ShapeType.RECTANGLE)}
138
- <Rectangle annotation={annotation} geom={selector.geometry} style={style} />
139
- {:else if (selector.type === ShapeType.POLYGON)}
140
- <Polygon annotation={annotation} geom={selector.geometry} style={style} />
150
+ {#if (selector?.type === ShapeType.ELLIPSE)}
151
+ <Ellipse
152
+ annotation={annotation}
153
+ geom={selector?.geometry}
154
+ style={style} />
155
+ {:else if (selector?.type === ShapeType.RECTANGLE)}
156
+ <Rectangle
157
+ annotation={annotation}
158
+ geom={selector.geometry}
159
+ style={style} />
160
+ {:else if (selector?.type === ShapeType.POLYGON)}
161
+ <Polygon
162
+ annotation={annotation}
163
+ geom={selector.geometry}
164
+ style={style} />
141
165
  {/if}
142
166
  {/key}
143
167
  {/if}
@@ -150,16 +174,19 @@
150
174
  {#if drawingEl}
151
175
  {#if editableAnnotations}
152
176
  {#each editableAnnotations as editable}
153
- {#key editable.id}
154
- <EditorMount
155
- target={drawingEl}
156
- editor={getEditor(editable.target.selector)}
157
- annotation={editable}
158
- style={style}
159
- transform={transform}
160
- viewportScale={$scale}
161
- on:change={onChangeSelected(editable)} />
162
- {/key}
177
+ {@const editor = getEditor(editable.target.selector)}
178
+ {#if editor}
179
+ {#key editable.id}
180
+ <EditorMount
181
+ target={drawingEl}
182
+ editor={getEditor(editable.target.selector)}
183
+ annotation={editable}
184
+ style={style}
185
+ transform={transform}
186
+ viewportScale={$scale}
187
+ on:change={onChangeSelected(editable)} />
188
+ {/key}
189
+ {/if}
163
190
  {/each}
164
191
  {:else if (tool && drawingEnabled)}
165
192
  {#key toolName}
@@ -174,4 +201,4 @@
174
201
  {/if}
175
202
  {/if}
176
203
  </g>
177
- </svg>
204
+ </svg>
@@ -39,7 +39,7 @@ export const addEventListeners = (svg: SVGSVGElement, store: SvelteImageAnnotati
39
39
  return { onPointerDown, onPointerUp };
40
40
  }
41
41
 
42
- const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
42
+ export const getSVGPoint = (evt: PointerEvent, svg: SVGSVGElement) => {
43
43
  const pt = svg.createSVGPoint();
44
44
  const bbox = svg.getBoundingClientRect();
45
45
 
@@ -4,8 +4,8 @@ import { PolygonEditor } from './polygon';
4
4
  import { RectangleEditor } from './rectangle';
5
5
 
6
6
  const REGISTERED = new Map<ShapeType, typeof SvelteComponent>([
7
- [ShapeType.RECTANGLE, RectangleEditor],
8
- [ShapeType.POLYGON, PolygonEditor]
7
+ [ShapeType.RECTANGLE, RectangleEditor as typeof SvelteComponent],
8
+ [ShapeType.POLYGON, PolygonEditor as typeof SvelteComponent]
9
9
  ]);
10
10
 
11
11
  export const getEditor = (shape: Shape) => REGISTERED.get(shape.type);
@@ -11,23 +11,31 @@ import type { W3CImageAnnotation } from './W3CImageAnnotation';
11
11
 
12
12
  export type W3CImageFormatAdapter = FormatAdapter<ImageAnnotation, W3CImageAnnotation>;
13
13
 
14
+ export interface W3CImageFormatAdapterOpts {
15
+
16
+ strict: boolean;
17
+
18
+ invertY: boolean;
19
+
20
+ }
21
+
14
22
  export const W3CImageFormat = (
15
23
  source: string,
16
- invertY: boolean = false
24
+ opts: W3CImageFormatAdapterOpts = { strict: true, invertY: false }
17
25
  ): W3CImageFormatAdapter => {
18
26
 
19
27
  const parse = (serialized: W3CAnnotation) =>
20
- parseW3CImageAnnotation(serialized, invertY);
28
+ parseW3CImageAnnotation(serialized, opts);
21
29
 
22
30
  const serialize = (annotation: ImageAnnotation) =>
23
- serializeW3CImageAnnotation(annotation, source);
31
+ serializeW3CImageAnnotation(annotation, source, opts);
24
32
 
25
33
  return { parse, serialize }
26
34
  }
27
35
 
28
36
  export const parseW3CImageAnnotation = (
29
37
  annotation: W3CAnnotation,
30
- invertY: boolean = false
38
+ opts: W3CImageFormatAdapterOpts
31
39
  ): ParseResult<ImageAnnotation> => {
32
40
  const annotationId = annotation.id || uuidv4();
33
41
 
@@ -39,7 +47,7 @@ export const parseW3CImageAnnotation = (
39
47
  ...rest
40
48
  } = annotation;
41
49
 
42
- const bodies = parseW3CBodies(body, annotationId);
50
+ const bodies = parseW3CBodies(body || [], annotationId);
43
51
 
44
52
  const w3cTarget = Array.isArray(annotation.target)
45
53
  ? annotation.target[0] : annotation.target;
@@ -49,11 +57,11 @@ export const parseW3CImageAnnotation = (
49
57
 
50
58
  const selector =
51
59
  w3cSelector?.type === 'FragmentSelector' ?
52
- parseFragmentSelector(w3cSelector as FragmentSelector, invertY) :
60
+ parseFragmentSelector(w3cSelector as FragmentSelector, opts.invertY) :
53
61
  w3cSelector?.type === 'SvgSelector' ?
54
62
  parseSVGSelector(w3cSelector as SVGSelector) : undefined;
55
63
 
56
- return selector ? {
64
+ return (selector || !opts.strict) ? {
57
65
  parsed: {
58
66
  ...rest,
59
67
  id: annotationId,
@@ -64,18 +72,18 @@ export const parseW3CImageAnnotation = (
64
72
  updated: modified ? new Date(modified) : undefined,
65
73
  ...(Array.isArray(rest.target) ? rest.target[0] : rest.target),
66
74
  annotation: annotationId,
67
- selector
75
+ selector: selector || w3cSelector
68
76
  }
69
77
  }
70
78
  } : {
71
79
  error: Error(`Invalid selector: ${JSON.stringify(w3cSelector)}`)
72
80
  };
73
-
74
81
  }
75
82
 
76
83
  export const serializeW3CImageAnnotation = (
77
84
  annotation: ImageAnnotation,
78
- source: string
85
+ source: string,
86
+ opts: W3CImageFormatAdapterOpts
79
87
  ): W3CImageAnnotation => {
80
88
  const {
81
89
  selector,
@@ -86,10 +94,18 @@ export const serializeW3CImageAnnotation = (
86
94
  ...rest
87
95
  } = annotation.target;
88
96
 
89
- const w3CSelector =
90
- selector.type == ShapeType.RECTANGLE ?
97
+ let w3cSelector: FragmentSelector | SVGSelector | unknown;
98
+
99
+ try {
100
+ w3cSelector = selector.type == ShapeType.RECTANGLE ?
91
101
  serializeFragmentSelector(selector.geometry as RectangleGeometry) :
92
102
  serializeSVGSelector(selector);
103
+ } catch (error) {
104
+ if (opts.strict)
105
+ throw error;
106
+ else
107
+ w3cSelector = selector;
108
+ }
93
109
 
94
110
  const serialized = {
95
111
  ...annotation,
@@ -103,7 +119,7 @@ export const serializeW3CImageAnnotation = (
103
119
  target: {
104
120
  ...rest,
105
121
  source,
106
- selector: w3CSelector
122
+ selector: w3cSelector
107
123
  }
108
124
  } as W3CImageAnnotation;
109
125
 
@@ -37,7 +37,7 @@ export const createImageAnnotatorState = <E extends unknown>(
37
37
 
38
38
  const tree = createSpatialTree();
39
39
 
40
- const selection = createSelectionState(store, opts.pointerSelectAction);
40
+ const selection = createSelectionState(store, opts.userSelectAction);
41
41
 
42
42
  const hover = createHoverState(store);
43
43
 
@@ -85,4 +85,3 @@ export const createSvelteImageAnnotatorState = <E extends unknown>(
85
85
  }
86
86
 
87
87
  }
88
-
@@ -54,10 +54,16 @@ export const createSpatialTree = () => {
54
54
  if (replace)
55
55
  clear();
56
56
 
57
- const indexedTargets = targets.map(target => {
58
- const { minX, minY, maxX, maxY } = target.selector.geometry.bounds;
59
- return { minX, minY, maxX, maxY, target };
60
- });
57
+ const indexedTargets = targets.reduce<IndexedTarget[]>((all, target) => {
58
+ if (target.selector?.geometry?.bounds) {
59
+ // In case the host app injects any custom annotations, the
60
+ // spatial index should simply ignore them.
61
+ const { minX, minY, maxX, maxY } = target.selector.geometry.bounds;
62
+ return [...all, { minX, minY, maxX, maxY, target }];
63
+ } else {
64
+ return all;
65
+ }
66
+ }, []);
61
67
 
62
68
  indexedTargets.forEach(t => index.set(t.target.annotation, t));
63
69
  tree.load(indexedTargets);