aiiinotate 0.2.0
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.
- package/LICENSE +661 -0
- package/README.md +61 -0
- package/cli/import.js +142 -0
- package/cli/index.js +26 -0
- package/cli/io.js +105 -0
- package/cli/migrate.js +123 -0
- package/cli/mongoClient.js +11 -0
- package/docs/architecture.md +88 -0
- package/docs/db.md +38 -0
- package/docs/dev_iiif_compatibility.md +43 -0
- package/docs/endpoints.md +48 -0
- package/docs/progress.md +159 -0
- package/docs/specifications/0_w3c_open_annotations.md +332 -0
- package/docs/specifications/1_w3c_web_annotations.md +577 -0
- package/docs/specifications/2_iiif_apis.md +396 -0
- package/docs/specifications/3_iiif_annotations.md +103 -0
- package/docs/specifications/4_search_api.md +135 -0
- package/docs/specifications/5_sas.md +119 -0
- package/docs/specifications/6_mirador.md +119 -0
- package/docs/specifications/7_aikon.md +137 -0
- package/docs/specifications/include/presentation_2.0.webp +0 -0
- package/docs/specifications/include/presentation_2.0_white.png +0 -0
- package/docs/specifications/include/presentation_3.0.png +0 -0
- package/docs/specifications/include/presentation_3.0_resize.png +0 -0
- package/eslint.config.js +27 -0
- package/migrations/baseConfig.js +56 -0
- package/migrations/manageIndex.js +55 -0
- package/migrations/migrate-mongo-config-main.js +8 -0
- package/migrations/migrate-mongo-config-test.js +8 -0
- package/migrations/migrationScripts/20250825185706-collections.js +41 -0
- package/migrations/migrationScripts/20250826194832-annotations2-canvas-index.js +31 -0
- package/migrations/migrationScripts/20250904080710-annotations2-schema.js +42 -0
- package/migrations/migrationScripts/20251002141951-manifest2-schema.js +43 -0
- package/migrations/migrationScripts/20251006212110-manifest-unique-index.js +29 -0
- package/migrations/migrationScripts/20251028115614-annotations2-id-index.js +27 -0
- package/migrations/migrationTemplate.js +25 -0
- package/package.json +78 -0
- package/run.sh +70 -0
- package/scripts/_migrations.sh +79 -0
- package/scripts/_setup.js +31 -0
- package/scripts/setup_mongodb.sh +61 -0
- package/scripts/setup_mongodb_migrate.sh +17 -0
- package/scripts/setup_node.sh +15 -0
- package/scripts/utils.sh +192 -0
- package/setup.sh +20 -0
- package/src/app.js +113 -0
- package/src/config/.env.template +22 -0
- package/src/data/annotations/annotations2.js +419 -0
- package/src/data/annotations/annotations3.js +32 -0
- package/src/data/annotations/routes.js +271 -0
- package/src/data/annotations/routes.test.js +180 -0
- package/src/data/collectionAbstract.js +270 -0
- package/src/data/index.js +29 -0
- package/src/data/manifests/manifests2.js +305 -0
- package/src/data/manifests/manifests2.test.js +53 -0
- package/src/data/manifests/manifests3.js +23 -0
- package/src/data/manifests/routes.js +95 -0
- package/src/data/manifests/routes.test.js +69 -0
- package/src/data/routes.js +141 -0
- package/src/data/routes.test.js +117 -0
- package/src/data/utils/iiif2Utils.js +196 -0
- package/src/data/utils/iiif2Utils.test.js +98 -0
- package/src/data/utils/iiif3Utils.js +0 -0
- package/src/data/utils/iiifUtils.js +18 -0
- package/src/data/utils/routeUtils.js +109 -0
- package/src/data/utils/testUtils.js +253 -0
- package/src/data/utils/utils.js +231 -0
- package/src/db/index.js +48 -0
- package/src/fileServer/annotations.js +39 -0
- package/src/fileServer/data/annotationList_aikon_wit9_man11_anno165_all.jsonld +827 -0
- package/src/fileServer/data/annotationList_vhs_wit250_man250_anno250_all.jsonld +37514 -0
- package/src/fileServer/data/annotationList_vhs_wit253_man253_anno253_all.jsonld +20111 -0
- package/src/fileServer/data/annotations2Invalid.jsonld +39 -0
- package/src/fileServer/data/annotations2Valid.jsonld +39 -0
- package/src/fileServer/data/bnf_invalid_manifest.json +2806 -0
- package/src/fileServer/data/bnf_valid_manifest.json +2817 -0
- package/src/fileServer/data/vhs_wit253_man253_anno253_anno-24.json +1 -0
- package/src/fileServer/index.js +64 -0
- package/src/fileServer/manifests.js +14 -0
- package/src/fileServer/utils.js +35 -0
- package/src/schemas/index.js +20 -0
- package/src/schemas/schemasBase.js +47 -0
- package/src/schemas/schemasPresentation2.js +417 -0
- package/src/schemas/schemasPresentation3.js +57 -0
- package/src/schemas/schemasResolver.js +71 -0
- package/src/schemas/schemasRoutes.js +277 -0
- package/src/server.js +22 -0
- package/src/types.js +93 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# IIIF APIs
|
|
2
|
+
|
|
3
|
+
This document is a summary of relevant elements of the IIIF specifications, and especially of the IIIF Presentation APIs. See [this document](./3_iiif_annotations.md) for a more focused look on annotations.
|
|
4
|
+
|
|
5
|
+
## Specifications
|
|
6
|
+
|
|
7
|
+
- image API docs [here](https://iiif.io/api/image/3.0/)
|
|
8
|
+
- presentation API 2.x [here](https://iiif.io/api/presentation/2.1/) (most widely used)
|
|
9
|
+
- presentation API 3.0 [here](https://iiif.io/api/presentation/3.0/) (newest version)
|
|
10
|
+
- relationship to the W3C annotations data model [here](https://iiif.io/api/annex/openannotation/)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Image API
|
|
15
|
+
|
|
16
|
+
[https://iiif.io/api/image/3.0/](https://iiif.io/api/image/3.0/)
|
|
17
|
+
|
|
18
|
+
The Annotation API is based on the IIIF image api. As a reminder, the IIIF image URL anatomy is:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
{scheme}://{server}{/prefix}/{identifier}/{region}/{size}/{rotation}/{quality}.{format}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Relation to the W3C Web Annotation model
|
|
27
|
+
|
|
28
|
+
[https://iiif.io/api/annex/openannotation](https://iiif.io/api/annex/openannotation)
|
|
29
|
+
|
|
30
|
+
IIIF 3.0 is based on the W3C Web Annotation data model (2.0 is based on Open Annotations), and not just for the IIIF annotations but for all its APIs ! In IIIF annotations, document parts are targeted as `SpecificResource`. The IIIF standard defines several custom selectors to extend the W3C standard.
|
|
31
|
+
|
|
32
|
+
### `ImageApiSelector`
|
|
33
|
+
|
|
34
|
+
Selects an image region in an Image API way. The selector is an *objectified* version of the Image API URL params:
|
|
35
|
+
|
|
36
|
+
- `type`: `"ImageApiSelector"`
|
|
37
|
+
- must be "ImageApiSelector"
|
|
38
|
+
- `region`:
|
|
39
|
+
- default `"full"`
|
|
40
|
+
- `size`:
|
|
41
|
+
- default `"full"`
|
|
42
|
+
- `rotation`:
|
|
43
|
+
- default `"0"`
|
|
44
|
+
- `quality`:
|
|
45
|
+
- default `"default"`
|
|
46
|
+
- `format`:
|
|
47
|
+
- default `"jpg"`
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
{
|
|
51
|
+
"type": "SpecificResource",
|
|
52
|
+
"source": "https://example.org/iiif/image1",
|
|
53
|
+
"selector": {
|
|
54
|
+
"type": "ImageApiSelector",
|
|
55
|
+
"region": "pct:0,0,10,10",
|
|
56
|
+
"rotation": "90"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### `PointSelector`
|
|
62
|
+
|
|
63
|
+
Selects a Point in an image.
|
|
64
|
+
|
|
65
|
+
- `type`: `"PointSelector"`
|
|
66
|
+
- `x`, `y`: `int`
|
|
67
|
+
- optional
|
|
68
|
+
- integers giving the x and y-coordinates of the point
|
|
69
|
+
- `t`: `float`
|
|
70
|
+
- optional
|
|
71
|
+
- float value describing the time at which the point appears (on a video), in seconds
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
{
|
|
75
|
+
"type": "PointSelector",
|
|
76
|
+
"x": 10,
|
|
77
|
+
"y": 10,
|
|
78
|
+
"t": 14.5
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Content Selectors
|
|
83
|
+
|
|
84
|
+
Out of scope here, but there are `AudioContentSelector` and `VisualContentSelector` to select audio/visual content in a IIIF video.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Presentation API (in general)
|
|
89
|
+
|
|
90
|
+
<table>
|
|
91
|
+
<tr>
|
|
92
|
+
<th>IIIF Presentation 3.0 data model</th>
|
|
93
|
+
<th>IIIF Presentation 2.0 data model</th>
|
|
94
|
+
</tr>
|
|
95
|
+
<tr>
|
|
96
|
+
<td><img src="./include/presentation_3.0_resize.png"></td>
|
|
97
|
+
<td><img src="./include/presentation_2.0_white.png"></td>
|
|
98
|
+
</tr>
|
|
99
|
+
</table>
|
|
100
|
+
|
|
101
|
+
### Terminology
|
|
102
|
+
|
|
103
|
+
- `embedded`: a resource that is included in the same document as a parent resource, called the embedder
|
|
104
|
+
- `referenced`: a resource that is not (entierly) present in another resource, and for which it is necessary to fetch the referenced resource's id to retrieve information
|
|
105
|
+
- `Annotations`, in the IIIF specifications, are not just "comments made on an image". Since IIIF APIs v2.x and 3.0 are based on Web Annotations specifications (W3C annotations for the v3.0, Open Annotations for the v.2.x), annotations are used in general to connect content to a Canvas. In turn, the image painted on a canvas is an annotation, since content is connected to Canvases using Web Annotations. Text, images etc that are comments on the image on a canvas are also annotations. To differenciate, there are 2 kinds of annotations:
|
|
106
|
+
- `painting annotations`: the primary content of a Canvas that will be displayed.
|
|
107
|
+
- `non-painting annotations`: annotations that are "about the canvas" (like transcriptions of a document)
|
|
108
|
+
|
|
109
|
+
### Differences between 2.0 and 3.0:
|
|
110
|
+
|
|
111
|
+
- 2.0 is mostly aimed at image documents (books), 3.0 also allows for audio-video documents
|
|
112
|
+
- (image) annotations in the 2.0 specification follow the Open Annotations standard, while 3.0 follows the W3C Web Annotations standard, derived from the former.
|
|
113
|
+
- ressources `AnnotationCollection` and `AnnotationPage` exist only in 3.0, and `Sequence` and `AnnotationList` exist only in 2.x.
|
|
114
|
+
- some vocabularies and attributes are modified (`@id` attribute in 2.0 become `id` in 3.0, `oa:Annotation` value in `2.0` becomes `Annotation` in 3.0, `sc:painting` value in 2.0 becomes `painting` in 3.0)
|
|
115
|
+
- 3.0 is more modular and allows for more embedded ressources.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Presentation API 3.0
|
|
120
|
+
|
|
121
|
+
> NOTE: only some general informations on the manifest's structure and the way images are embedded in the manifest is included.
|
|
122
|
+
|
|
123
|
+
### Ressource types
|
|
124
|
+
|
|
125
|
+
- `Collection`: an ordered list of Manifests or Collections of Manifests
|
|
126
|
+
- `Manifest`: a description of the structure and properties of the compound object (book...)
|
|
127
|
+
- `Range`: an ordered list of Canvases, or Range of Canvases
|
|
128
|
+
- `Canvas`: a virtual container that represents a particular view of the object and has content resources associated to it. The Canvas allows to describe how content is laid out on it, spatially and temporally. Annotations are used to populate the Canvas with images, text, sound...
|
|
129
|
+
- `Annotation Collection`: a list of Annotation Pages that allows higher level-groupings (different ttranscriptions of a single text may each get their Annotation Collection)
|
|
130
|
+
- `Annotation Page`: an ordered list of Annotations associated with a Canvas. Annotation Pages can also provide commentary on a resource that is part of a canvas (like a text commentary for an image)
|
|
131
|
+
- `Annotation`: annotations are used to store a canvas' content: image, video, text...
|
|
132
|
+
|
|
133
|
+
### Images and Annotations in the manifest
|
|
134
|
+
|
|
135
|
+
The global structure is:
|
|
136
|
+
> `Canvas / AnnotationPage[] / Annotation[]`
|
|
137
|
+
|
|
138
|
+
#### Canvas
|
|
139
|
+
|
|
140
|
+
The `Canvas` represents a single page (for a book) or a single view within a manifest.
|
|
141
|
+
- `id` MUST be used and MUST be a URI identifying the canvas.
|
|
142
|
+
- `type`: `AnnotationPage`
|
|
143
|
+
- a canvas MAY be embedded or referenced within the parent manifest
|
|
144
|
+
- content is associated to a `Canvas` through Web annotations.
|
|
145
|
+
- `id` MUST be used and MUST be a URI identifying the canvas.
|
|
146
|
+
- `items` is the property containing a list of AnnotationPages
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
{
|
|
150
|
+
// Metadata about this canvas
|
|
151
|
+
"id": "https://example.org/iiif/book1/canvas/p1",
|
|
152
|
+
"type": "Canvas",
|
|
153
|
+
"label": { "none": [ "p. 1" ] },
|
|
154
|
+
"height": 1000,
|
|
155
|
+
"width": 750,
|
|
156
|
+
|
|
157
|
+
"items": [
|
|
158
|
+
{
|
|
159
|
+
"id": "https://example.org/iiif/book1/content/p1/1",
|
|
160
|
+
"type": "AnnotationPage",
|
|
161
|
+
"items": [
|
|
162
|
+
// Painting Annotations on the Canvas are included here
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
],
|
|
166
|
+
|
|
167
|
+
"annotations": [
|
|
168
|
+
{
|
|
169
|
+
"id": "https://example.org/iiif/book1/comments/p1/1",
|
|
170
|
+
"type": "AnnotationPage",
|
|
171
|
+
"items": [
|
|
172
|
+
// Non-Painting Annotations on the Canvas are included here
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### AnnotationPage
|
|
181
|
+
|
|
182
|
+
An `AnnotationPage` contains a list of annotations.
|
|
183
|
+
- `id` MUST be used and MUST be a URI identifying the canvas.
|
|
184
|
+
- `type`: `AnnotationPage`
|
|
185
|
+
- the AnnotationPage MAY have any of the other properties defined in the Web Annotation specification
|
|
186
|
+
- an AnnotationPage may be embedded in the manifest, or referenced by the manifest.
|
|
187
|
+
- if embedded, the property `items` contains a list of Annotations
|
|
188
|
+
- if referenced, the AnnotationPage
|
|
189
|
+
- MUST have the minimal structure `{"id": "<uri>","type": "AnnotationPage"}`
|
|
190
|
+
- MUST NOT have the property `items`
|
|
191
|
+
- MAY contain other properties
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
{
|
|
195
|
+
"@context": "http://iiif.io/api/presentation/3/context.json",
|
|
196
|
+
"id": "https://example.org/iiif/book1/annopage/p1",
|
|
197
|
+
"type": "AnnotationPage",
|
|
198
|
+
|
|
199
|
+
"items": [
|
|
200
|
+
{
|
|
201
|
+
"id": "https://example.org/iiif/book1/annopage/p1/a1",
|
|
202
|
+
"type": "Annotation"
|
|
203
|
+
// ...
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"id": "https://example.org/iiif/book1/annopage/p1/a2",
|
|
207
|
+
"type": "Annotation"
|
|
208
|
+
// ...
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Annotation
|
|
215
|
+
|
|
216
|
+
**`Annotations`** store a canvas' content.
|
|
217
|
+
- annotations are contained within `AnnotationPage`s
|
|
218
|
+
- there are 2 types of Annotations: painting and non-painting Annotations. Painting Annotations will be rendered as the canvas' content while non-painting Annotations are *about* the canvas in another way.
|
|
219
|
+
- `id` MUST be used and MUST be a URI
|
|
220
|
+
- `type`: `Annotation`
|
|
221
|
+
- `target` SHOULD contain a reference to the Canvas' `id`
|
|
222
|
+
- `motivation` is the property describing the role of the Annotation (painting or non-painting):
|
|
223
|
+
- painting Annotations MUST have the attribute `motivation: "painting"` (rendered annotations ar the images that will be visible on the canvas)
|
|
224
|
+
- informations derived from the Canvas's content (like the OCR of a text page) MUST be associated by an Annotation with `motivation: "supplementing"`
|
|
225
|
+
- in short, content of any type may be associated with the Canvas via an Annotation that has the `motivation` value `painting`, meaning the content is part of the Canvas; an Annotation that has the `motivation` value `supplementing`, meaning the content is from the Canvas but not necessarily part of it; or an Annotation with another `motivation` meaning that it is somehow about the Canvas.
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
{
|
|
229
|
+
"@context": "http://iiif.io/api/presentation/3/context.json",
|
|
230
|
+
"id": "https://example.org/iiif/book1/annotation/p0001-image",
|
|
231
|
+
"type": "Annotation",
|
|
232
|
+
"motivation": "painting",
|
|
233
|
+
"body": {
|
|
234
|
+
"id": "https://example.org/images/page1.jpg",
|
|
235
|
+
"type": "Image"
|
|
236
|
+
},
|
|
237
|
+
"target": "https://example.org/iiif/book1/canvas/p1"
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
#### AnnotationCollection
|
|
242
|
+
|
|
243
|
+
The `AnnotationCollection` object is used to group sevral AnnotationPages that should be managed together, regardless of the Canvas resource they target. For example, an AnnotationCollection may be a single translation of a text, thus allowing to have several translation for a text.
|
|
244
|
+
- `id` MUST be used and MUST be an URI
|
|
245
|
+
- `label` SHOULD be used to display infor;ation the collection
|
|
246
|
+
- other properties MAY be used.
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
{
|
|
250
|
+
"@context": "http://iiif.io/api/presentation/3/context.json",
|
|
251
|
+
"id": "https://example.org/iiif/book1/annocoll/transcription",
|
|
252
|
+
"type": "AnnotationCollection",
|
|
253
|
+
"label": {"en": ["Diplomatic Transcription"]},
|
|
254
|
+
"first": { "id": "https://example.org/iiif/book1/annopage/l1", "type": "AnnotationPage" },
|
|
255
|
+
"last": { "id": "https://example.org/iiif/book1/annopage/l120", "type": "AnnotationPage" }
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Presentation API 2.0
|
|
262
|
+
|
|
263
|
+
### Ressource types
|
|
264
|
+
|
|
265
|
+
- `Manifest`
|
|
266
|
+
- `Sequence`: the order of the views in the object. A manifest may contain several Sequences to describe multiple equally valid orders in the content
|
|
267
|
+
- `Canvas`: container for a single or view
|
|
268
|
+
- `Content`: content resources, such as image or text associated with a canvas.
|
|
269
|
+
|
|
270
|
+
### Images in the manifest
|
|
271
|
+
|
|
272
|
+
#### Canvas
|
|
273
|
+
|
|
274
|
+
A `Canvas` represents a single view within the manifest. It is a 2D rectangular shape with a defined `width` and `height` defined as positive integers.
|
|
275
|
+
- images are linked to a canvas as Annotatios that are embedded in the `images` property
|
|
276
|
+
- `images` stores the image annotations
|
|
277
|
+
- `otherContent` stores references to other annotation lists: transcriptions, commentary etc.
|
|
278
|
+
- an canvas MAY be embedded or referenced from the manifest by an URI.
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
{
|
|
282
|
+
// Metadata about this canvas
|
|
283
|
+
"@context": "http://iiif.io/api/presentation/2/context.json",
|
|
284
|
+
"@id": "http://example.org/iiif/book1/canvas/p1",
|
|
285
|
+
"@type": "sc:Canvas",
|
|
286
|
+
"label": "p. 1",
|
|
287
|
+
"height": 1000,
|
|
288
|
+
"width": 750,
|
|
289
|
+
"thumbnail" : {
|
|
290
|
+
"@id" : "http://example.org/iiif/book1/canvas/p1/thumb.jpg",
|
|
291
|
+
"@type": "dctypes:Image",
|
|
292
|
+
"height": 200,
|
|
293
|
+
"width": 150
|
|
294
|
+
},
|
|
295
|
+
"images": [
|
|
296
|
+
{
|
|
297
|
+
"@type": "oa:Annotation"
|
|
298
|
+
// Link from Image to canvas should be included here, as below
|
|
299
|
+
}
|
|
300
|
+
],
|
|
301
|
+
"otherContent": [
|
|
302
|
+
{
|
|
303
|
+
// Reference to list of other Content resources, _not included directly_
|
|
304
|
+
"@id": "http://example.org/iiif/book1/list/p1",
|
|
305
|
+
"@type": "sc:AnnotationList"
|
|
306
|
+
}
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
#### Image resource
|
|
313
|
+
|
|
314
|
+
Image ressources are Annotations linked to the canvas.
|
|
315
|
+
- `@id` MAY be used to identify the image and SHOULD be an HTTP URI if used
|
|
316
|
+
- `motivation` MUST be used and its value MUST be `sc:painting` to distinguish it from non-painting annotations
|
|
317
|
+
- `resource` is the property linking the image itself to the annotation
|
|
318
|
+
- `@id` MUST be used and MUST be the URI at which the image is accessed and the URI MAY be a IIIF image URI.
|
|
319
|
+
- `@type: "dtypes:Image"` shuld be used
|
|
320
|
+
- `format` may be used to describe the image's mediatype
|
|
321
|
+
- `on` attribute MUST be used and the value MUST be the Canvas' `@id`
|
|
322
|
+
|
|
323
|
+
```js
|
|
324
|
+
{
|
|
325
|
+
"@context": "http://iiif.io/api/presentation/2/context.json",
|
|
326
|
+
"@id": "http://example.org/iiif/book1/annotation/p0001-image",
|
|
327
|
+
"@type": "oa:Annotation",
|
|
328
|
+
"motivation": "sc:painting",
|
|
329
|
+
"resource": {
|
|
330
|
+
"@id": "http://example.org/iiif/book1/res/page1.jpg",
|
|
331
|
+
"@type": "dctypes:Image",
|
|
332
|
+
"format": "image/jpeg",
|
|
333
|
+
"service": {
|
|
334
|
+
"@context": "http://iiif.io/api/image/2/context.json",
|
|
335
|
+
"@id": "http://example.org/images/book1-page1",
|
|
336
|
+
"profile": "http://iiif.io/api/image/2/level2.json"
|
|
337
|
+
},
|
|
338
|
+
"height":2000,
|
|
339
|
+
"width":1500
|
|
340
|
+
},
|
|
341
|
+
"on": "http://example.org/iiif/book1/canvas/p1"
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### AnnotationList
|
|
346
|
+
|
|
347
|
+
`AnnotationList`s are used to add additional resources to the canvas: the full text of the object...
|
|
348
|
+
- they are collections of annotatins
|
|
349
|
+
- they MUST be referenced from the canvas they are associated with by an URI. they MUST NOT be embedded in the manifest.
|
|
350
|
+
- they SHOULD be loaded by the client when they are encountered.
|
|
351
|
+
- separation between Canvas and AnnotationList allows to accelerate loading time for the manifest (it is lighter since it does not contain all extra annotations).
|
|
352
|
+
|
|
353
|
+
URI pattern : `{scheme}://{host}/{prefix}/{identifier}/list/{name}`
|
|
354
|
+
- `{name}` MUST identify uniquely the list. the name MAY be the canvas' name, but since a canvas may have several annotations it must not be assumed that the list's and the canvas' name will be the same.
|
|
355
|
+
|
|
356
|
+
Properties of the annotation list are:
|
|
357
|
+
- `@id`: MUST be the HTTPS URI used to access the AnnotationList
|
|
358
|
+
- `resources` is a list of annotations
|
|
359
|
+
- each resource MUST be something other than an image if the `motivation` is `sc:painting` (a Canvas' painting images is defined by its `images` key)
|
|
360
|
+
- `on` property MUST be used and point to the canvas' `@id`
|
|
361
|
+
- `format` SHOULD be included and MUST be the ressource's media type
|
|
362
|
+
- `motivation` is used to describe the role of the resource. if the resource is to be rendered it MUST be `sc:painting` (such as images, text transcriptions, performances of music from the manuscript and so forth)
|
|
363
|
+
- other possible properties are: `label`, `description`, `metadata`, `license` and `attribution`
|
|
364
|
+
|
|
365
|
+
```js
|
|
366
|
+
{
|
|
367
|
+
"@context": "http://iiif.io/api/presentation/2/context.json",
|
|
368
|
+
"@id": "http://example.org/iiif/book1/list/p1",
|
|
369
|
+
"@type": "sc:AnnotationList",
|
|
370
|
+
|
|
371
|
+
"resources": [
|
|
372
|
+
{
|
|
373
|
+
"@type": "oa:Annotation",
|
|
374
|
+
"motivation": "sc:painting",
|
|
375
|
+
"resource":{
|
|
376
|
+
"@id": "http://example.org/iiif/book1/res/music.mp3",
|
|
377
|
+
"@type": "dctypes:Sound",
|
|
378
|
+
"format": "audio/mpeg"
|
|
379
|
+
},
|
|
380
|
+
"on": "http://example.org/iiif/book1/canvas/p1"
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"@type": "oa:Annotation",
|
|
384
|
+
"motivation": "sc:painting",
|
|
385
|
+
"resource":{
|
|
386
|
+
"@id": "http://example.org/iiif/book1/res/tei-text-p1.xml",
|
|
387
|
+
"@type": "dctypes:Text",
|
|
388
|
+
"format": "application/tei+xml"
|
|
389
|
+
},
|
|
390
|
+
"on": "http://example.org/iiif/book1/canvas/p1"
|
|
391
|
+
}
|
|
392
|
+
// ... and so on
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# IIIF ANNOTATIONS
|
|
2
|
+
|
|
3
|
+
This document focuses on the way annotations are handled in IIIF. For a more general on IIIF APIs, see [this document](./2_iiif_apis.md)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Sources
|
|
8
|
+
|
|
9
|
+
- [IIIF 3.0 annotation example](https://iiif.io/api/cookbook/recipe/0266-full-canvas-annotation/)
|
|
10
|
+
- [IIIF annotations tutorial](https://training.iiif.io/iiif-online-workshop/day-four/annotations-and-annotation-lists.html)
|
|
11
|
+
- step 4 of [this tutorial](https://training.iiif.io/iiif-online-workshop/day-four/annotation-linking.html) explains how to link annotations to a manifest in 2.x
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## TLDR
|
|
16
|
+
|
|
17
|
+
In `Presentation API 3.0`, non-painting Annotations (i.e, textual annotations) are included in Canvases using the `annotations`. The structure of a canvas is then:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
canvas
|
|
21
|
+
|_items : AnnotationPage[] // painting annotations. embedded
|
|
22
|
+
|_annotations : AnnotationPage[] // non-painting annotations. should be referenced
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
In `Presentation API 2.x`, non-painting Annotations are included in canvases using the `otherContent` key:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
canvas
|
|
29
|
+
|_images : Annotation[] // painting annotations. embedded
|
|
30
|
+
|_otherContent : AnnotationList[] // non-painting annotations. should be referenced
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Presentation API 3.0
|
|
36
|
+
|
|
37
|
+
The structre of an AnnotationPage is:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
{
|
|
41
|
+
"@context": "http://iiif.io/api/presentation/3/context.json",
|
|
42
|
+
"id": "https://example.org/iiif/book1/annopage/p1",
|
|
43
|
+
"type": "AnnotationPage",
|
|
44
|
+
|
|
45
|
+
"items": [
|
|
46
|
+
// annotations go here
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The structure of an annotation is:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
{
|
|
55
|
+
"@context": "http://iiif.io/api/presentation/3/context.json",
|
|
56
|
+
"id": "https://example.org/iiif/book1/annotation/p0001-image",
|
|
57
|
+
"type": "Annotation",
|
|
58
|
+
"motivation": "painting",
|
|
59
|
+
"body": {
|
|
60
|
+
"type": "TextualBody",
|
|
61
|
+
"value" : "<p>What a lovely annotation</p>",
|
|
62
|
+
"format" : "text/html",
|
|
63
|
+
"language" : "fr"
|
|
64
|
+
},
|
|
65
|
+
"target": "https://example.org/iiif/book1/canvas/p1"
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Presentation API 2.x
|
|
72
|
+
|
|
73
|
+
The structure of an AnnotationList is:
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
{
|
|
77
|
+
"@context": "http://iiif.io/api/presentation/2/context.json",
|
|
78
|
+
"@id": "http://example.org/iiif/book1/list/p1",
|
|
79
|
+
"@type": "sc:AnnotationList",
|
|
80
|
+
|
|
81
|
+
"resources": [
|
|
82
|
+
// annotations go here
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
And the structure of an Annotation is (with some extra metadata):
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
{
|
|
91
|
+
"@id" : "http://aikon.enpc.fr/sas/annotation/wit90_pdf105_anno195_c10_69f692ce732f42698208c05515d085de",
|
|
92
|
+
"@type" : "oa:Annotation",
|
|
93
|
+
"resource" : {
|
|
94
|
+
"@type" : "dctypes:Text",
|
|
95
|
+
"format" : "text/html",
|
|
96
|
+
"chars" : "<p>What a lovely annotation</p>",
|
|
97
|
+
},
|
|
98
|
+
"on" : "https://aikon.enpc.fr/aikon/iiif/v2/wit90_pdf105_anno195/canvas/c10.json#xywh=258,591,1016,738",
|
|
99
|
+
"motivation" : [ "oa:tagging", "oa:commenting" ],
|
|
100
|
+
"@context" : "http://iiif.io/api/presentation/2/context.json",
|
|
101
|
+
"label" : ""
|
|
102
|
+
}
|
|
103
|
+
```
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# IIIF Search API
|
|
2
|
+
|
|
3
|
+
Search API 1.0 (aligned with IIIF 2.1): [https://iiif.io/api/search/1.0/](https://iiif.io/api/search/1.0/)
|
|
4
|
+
|
|
5
|
+
Search API 2.0 (aligned with IIIF 3.0): [https://iiif.io/api/search/2.0/](https://iiif.io/api/search/2.0/)
|
|
6
|
+
|
|
7
|
+
The search API allows to query IIIF contents, such as a manifest, an annotation list/page or an annotation.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Versions
|
|
12
|
+
|
|
13
|
+
- Search API 1.0 is aligned with IIIF Presentation API 2.1. Query responses are `AnnotationLists`.
|
|
14
|
+
- Search API 2.0 is aligned with IIIF Presentation API 3.1. Query responses are `AnnotationPages`.
|
|
15
|
+
|
|
16
|
+
Other than that, the 2 APIs are pretty similar, so they are presented together.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Scope
|
|
21
|
+
|
|
22
|
+
IIIF Search is scoped: the IIIF search is made available by including a `service description` in part of a IIIF manifest (the manifest itself, an annotation list/page...)
|
|
23
|
+
|
|
24
|
+
### Search API 1.0
|
|
25
|
+
|
|
26
|
+
`@id` contains the URI where the search can be performed.
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
// ... the resource that the search service is associated with ...
|
|
30
|
+
"service": {
|
|
31
|
+
"@context": "http://iiif.io/api/search/1/context.json",
|
|
32
|
+
"@id": "http://example.org/services/identifier/search",
|
|
33
|
+
"profile": "http://iiif.io/api/search/1/search"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
### Search API 2.0
|
|
38
|
+
|
|
39
|
+
`id` contains the URI where the search can be performed.
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
{
|
|
43
|
+
// ... the resource that the search service is associated with ...
|
|
44
|
+
"service": [
|
|
45
|
+
{
|
|
46
|
+
"id": "https://example.org/services/identifier/search", // the URL where to run the search
|
|
47
|
+
"type": "SearchService2"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Search URL anatomy
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
GET https://example.org/services/identifier/search?q={...}&motivation={...}&date={...}&user={...}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Where:
|
|
62
|
+
|
|
63
|
+
- `q`: space-separated list of search terms. Those will be searched in Textual Bodies or URIs.
|
|
64
|
+
- `motivation`: space-separated list of motivations, queried in the `motivation` / `oa:motivation` fields.
|
|
65
|
+
- `date`: space-separated list of creation date ranges in `start/end` ISO8601 format: `YYYY-MM-DDThh:mm:ssZ/YYYY-MM-DDThh:mm:ssZ`. In IIIF 2.1, will be searched in the `dc:created` field of annotations.
|
|
66
|
+
- `user`: URI that identifies the user that created an annotation.
|
|
67
|
+
|
|
68
|
+
`q` MUST be implemented, `motivation` SHOULD be implemented, the others MAY be implemented.
|
|
69
|
+
|
|
70
|
+
*Example: `https://example.org/service/manifest/search?q=bird&motivation=painting`*
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Responses
|
|
75
|
+
|
|
76
|
+
### Search API 1.0
|
|
77
|
+
|
|
78
|
+
- the response MUST be in an `AnnotationList`
|
|
79
|
+
- `@id` MUST be the query URI
|
|
80
|
+
- results are an array of `Annotations` in the `resources` key.
|
|
81
|
+
|
|
82
|
+
More personnalisation can be done (pagnination, search-specific data in the AnnotationList, autocomplete etc.) but it's out of scope compared to our aims.
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
{
|
|
86
|
+
"@context":"http://iiif.io/api/presentation/2/context.json",
|
|
87
|
+
"@id":"http://example.org/service/manifest/search?q=bird&motivation=painting",
|
|
88
|
+
"@type":"sc:AnnotationList",
|
|
89
|
+
|
|
90
|
+
"resources": [
|
|
91
|
+
{
|
|
92
|
+
"@id": "http://example.org/identifier/annotation/anno-line",
|
|
93
|
+
"@type": "oa:Annotation",
|
|
94
|
+
"motivation": "sc:painting",
|
|
95
|
+
"resource": {
|
|
96
|
+
"@type": "cnt:ContentAsText",
|
|
97
|
+
"chars": "A bird in the hand is worth two in the bush"
|
|
98
|
+
},
|
|
99
|
+
"on": "http://example.org/identifier/canvas1#xywh=100,100,250,20"
|
|
100
|
+
}
|
|
101
|
+
// Further matching annotations here ...
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Search API 2.0
|
|
107
|
+
|
|
108
|
+
- the response MUST be an AnnotationPage
|
|
109
|
+
- `@id` MUST be the query URI
|
|
110
|
+
- annotations MUST be embedded in the response
|
|
111
|
+
|
|
112
|
+
It's possible to implement pagination and autocomplete, but this is out of bounds here.
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
{
|
|
116
|
+
"@context": "http://iiif.io/api/search/2/context.json",
|
|
117
|
+
"id": "https://example.org/service/manifest/search?q=bird&motivation=painting",
|
|
118
|
+
"type": "AnnotationPage",
|
|
119
|
+
|
|
120
|
+
"items": [
|
|
121
|
+
{
|
|
122
|
+
"id": "https://example.org/identifier/annotation/anno-line",
|
|
123
|
+
"type": "Annotation",
|
|
124
|
+
"motivation": "painting",
|
|
125
|
+
"body": {
|
|
126
|
+
"type": "TextualBody",
|
|
127
|
+
"value": "A bird in the hand is worth two in the bush",
|
|
128
|
+
"format": "text/plain"
|
|
129
|
+
},
|
|
130
|
+
"target": "https://example.org/identifier/canvas1#xywh=100,100,250,20"
|
|
131
|
+
}
|
|
132
|
+
// Further matching annotations here ...
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
```
|