From 158fca58f2fc8f381e003d321c1d8bdb90c79844 Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Mon, 16 Feb 2026 14:05:08 -0500 Subject: [PATCH 1/7] block in classes --- source/presentation/4.0/model.md | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/source/presentation/4.0/model.md b/source/presentation/4.0/model.md index 3234539e9..f9db939ae 100644 --- a/source/presentation/4.0/model.md +++ b/source/presentation/4.0/model.md @@ -487,6 +487,41 @@ A Choice _SHOULD_ have the following properties: [label](#label)

A Choice _MAY_ have the following properties: [id](#id), [metadata](#metadata), [summary](#summary), [provider](#provider), [thumbnail](#thumbnail), [requiredStatement](#requiredStatement), [behavior](#behavior), and [seeAlso](#seeAlso).

{: .note} +#### Composite +{: #Composite} + +> `"type": "Composite"` + +A Composite is a construction where all of the resources are required for , as opposed to Choice where the client selects only one of the items. + +__Properties__
+A Composite _MUST_ have the following properties: [type](#type), [items](#items)

+A Composite _SHOULD_ have the following properties: [label](#label)

+A Composite _MAY_ have the following properties: [id](#id), [metadata](#metadata), [summary](#summary), [provider](#provider), [thumbnail](#thumbnail), [requiredStatement](#requiredStatement), [behavior](#behavior), and [seeAlso](#seeAlso).

+{: .note} + +#### List +{: #List} + +> `"type": "List"` + +__Properties__
+A List _MUST_ have the following properties: [type](#type), [items](#items)

+A List _SHOULD_ have the following properties: [label](#label)

+A List _MAY_ have the following properties: [id](#id), [metadata](#metadata), [summary](#summary), [provider](#provider), [thumbnail](#thumbnail), [requiredStatement](#requiredStatement), [behavior](#behavior), and [seeAlso](#seeAlso).

+{: .note} + +#### Independents +{: #Independents} + +> `"type": "Independents"` + +__Properties__
+An Independents _MUST_ have the following properties: [type](#type), [items](#items)

+An Independents _SHOULD_ have the following properties: [label](#label)

+An Independents _MAY_ have the following properties: [id](#id), [metadata](#metadata), [summary](#summary), [provider](#provider), [thumbnail](#thumbnail), [requiredStatement](#requiredStatement), [behavior](#behavior), and [seeAlso](#seeAlso).

+{: .note} + ### Content Resources {: #ContentResources} From ef3d24df1e1b56461c6e11e6c7e2a5bff279d4a0 Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Mon, 16 Feb 2026 14:38:01 -0500 Subject: [PATCH 2/7] update body and target to require single json object, including aggregate constructions --- source/presentation/4.0/model.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/source/presentation/4.0/model.md b/source/presentation/4.0/model.md index f9db939ae..51669bc3d 100644 --- a/source/presentation/4.0/model.md +++ b/source/presentation/4.0/model.md @@ -492,7 +492,7 @@ A Choice _MAY_ have the following properties: [id](#id), [metadata](#metadata), > `"type": "Composite"` -A Composite is a construction where all of the resources are required for , as opposed to Choice where the client selects only one of the items. +A Composite is a Web Annotation construction where all of the resources are required for the correct interpretation of the set of resources in the context of the Annotation, as opposed to Choice where the client selects only one of the items or allows the user to make that selection. For Composite, the client should present all of the resources listed in the `items` property, however order or priority is not specified. For example, if a Composite is used as the `target` of a commenting Annotation, then it is the unordered set of resources that is being commented on. __Properties__
A Composite _MUST_ have the following properties: [type](#type), [items](#items)

@@ -505,6 +505,8 @@ A Composite _MAY_ have the following properties: [id](#id), [metadata](#metadata > `"type": "List"` +A List is a Web Annotation construction where all of the resources are required, in the given order, for the correct interpretation of the set. For example, if a List is used as the `target` of a commenting Annotation, then it is the ordered list of resources that are being commented on, rather than each independently. + __Properties__
A List _MUST_ have the following properties: [type](#type), [items](#items)

A List _SHOULD_ have the following properties: [label](#label)

@@ -516,6 +518,8 @@ A List _MAY_ have the following properties: [id](#id), [metadata](#metadata), [s > `"type": "Independents"` +An independents is a Web Annotation construction where each of the resources independently participates in the annotation, rather than as a set. For example, if an Independents is used as the `target` of a commenting Annotation, then the body resource is about each of the entries in `items` separately, rather than the collection as a single entity. In the Web Annotation Data Model this is equivalent to having multiple independent bodies or targets listed directly in the Annotation, however this specification requires a single resource for both body and target. + __Properties__
An Independents _MUST_ have the following properties: [type](#type), [items](#items)

An Independents _SHOULD_ have the following properties: [label](#label)

@@ -1352,13 +1356,13 @@ The value _MUST_ be an array of strings. ### body {: #body} -The list of bodies of an Annotation. As there _MAY_ be more than one body, the value _MUST_ be an array, even though the W3C specification does not require this. The resources listed in `body` can be instances of `TextualBody`, `SpecificResource`, core Structural Resources, or Content Resources. +The body of an Annotation. The resources listed in `body` can be instances of `TextualBody`, `SpecificResource`, core Structural Resources, Content Resources, or the Annotation aggregate constructions of `Choice`, `Composite`, `List` and `Independents` if there are multiple bodies. Some Annotations do not have bodies at all. For example a highlighting annotation only needs to visually highlight the region targeted. Note that use of the W3C `bodyValue` property is prohibited in IIIF, and the `TextualBody` class _MUST_ be used instead. For more information about Annotation bodies, see the [W3C Annotation Model](https://www.w3.org/TR/annotation-model/#bodies-and-targets). -The value _MUST_ be an array of JSON objects. Each item _MUST_ have the `type` property. Referenced resources _MUST_ have the `id` property. +The value _MUST_ be a JSON object. Each item _MUST_ have the `type` property. Referenced resources _MUST_ have the `id` property, which _MAY_ have a fragment component such as `#xywh=`. Aggregate constructions _MUST_ have the `items` property. * An Annotation _SHOULD_ have the `body` property.
Clients _MUST_ process the `body` property on Annotations. @@ -1366,9 +1370,7 @@ The value _MUST_ be an array of JSON objects. Each item _MUST_ have the `type` p {% include api/code_header.html %} ``` json-doc { "body": - [ - {"type": "TextualBody", "value": "Great!"} - ] + {"type": "TextualBody", "value": "Great!"} } ``` @@ -2749,18 +2751,20 @@ The value _MUST_ be a JSON object, which _MUST_ have the `id` and `type` propert ### target {: #target} -The list of targets of an Annotation. As there _MAY_ be more than one target, the value _MUST_ be an array, even though the W3C specification does not require this. The resources listed in `target` can be instances of `SpecificResource`, core Structural Resources, or Content Resources. +The target of an Annotation. The resources listed in `target` can be instances of `SpecificResource`, core Structural Resources, Content Resources, or one of the aggregate constructions of `Choice`, `Composite`, `List` and `Independents` if there are multiple targets. For more information about Annotation targets, see the [W3C Annotation Model](https://www.w3.org/TR/annotation-model/#bodies-and-targets). -The value _MUST_ be an array. Each item _MUST_ be a JSON object with the `type` property, and referenced resources _MUST_ also have the `id` property. +The value _MUST_ be a JSON Object. It _MUST_ have the `type` property. Referenced resources _MUST_ have the `id` property, which _MAY_ have a fragment component such as `#xywh=`. Aggregate constructions _MUST_ have the `items` property. * An Annotation _MUST_ have the `target` property.
Clients _MUST_ process the `target` property on Annotations. {% include api/code_header.html %} ``` json-doc -{ "target": [ { "id": "https://example.org/iiif/1/canvas/1", "type": "Canvas" } ] } +{ "target": + { "id": "https://example.org/iiif/1/canvas/1", "type": "Canvas" } +} ``` From 64106f84c8909c253a0c7f5d7e05c12e80abc20b Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Mon, 16 Feb 2026 14:09:58 -0500 Subject: [PATCH 3/7] Fix @mikeapp's comment re "currently" --- source/presentation/4.0/model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/presentation/4.0/model.md b/source/presentation/4.0/model.md index 51669bc3d..aaa946e82 100644 --- a/source/presentation/4.0/model.md +++ b/source/presentation/4.0/model.md @@ -2369,7 +2369,7 @@ The value _MUST_ be a string, not a number, in order to allow for the "!" charac ### scope {: #scope} -The scope of a Specific Resource is the context in which it should be interpreted, viewed, or used. For the purposes of IIIF, it is a pointer to one or more resources that are intended to be used by the client for the user to view or interact with the resource. In a Scene, this would typically be an instance of a Camera that should be activated and selected to set up the correct viewpoint. There are no specific expectations around other classes currently. +The scope of a Specific Resource is the context in which it should be interpreted, viewed, or used. For the purposes of IIIF, it is a pointer to one or more resources that are intended to be used by the client for the user to view or interact with the resource. In a Scene, this would typically be an instance of a Camera that should be activated and selected to set up the correct viewpoint. This specification does not establish specific expectations for references to other classes. The value _MUST_ be an array of JSON objects. From 11917a3d625e31d2423b9f2dadcbf50ca2c8d653 Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Tue, 17 Feb 2026 09:58:16 -0500 Subject: [PATCH 4/7] Up to Use Case 9 --- source/presentation/4.0/index.md | 375 +++++++++++++++++-------------- 1 file changed, 206 insertions(+), 169 deletions(-) diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md index b4e3a57c7..975d4dbfe 100644 --- a/source/presentation/4.0/index.md +++ b/source/presentation/4.0/index.md @@ -230,16 +230,18 @@ Canvases have two additional required properties: [`height`][prezi-40-model-heig "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/annotation/c1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://iiif.io/api/presentation/example-content-resources/image/painting.jpg", "type": "Image", "format": "image/jpeg", "width": 4000, "height": 3000 - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-containers/canvas"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/canvas". + "type": "Canvas" + } } ] } @@ -266,14 +268,17 @@ Scenes may also have the [`duration`][prezi-40-model-duration] property in the s "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/annotation/s1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://iiif.io/api/presentation/example-content-resources/models/astronaut.glb", "type": "Model", "format": "model/gltf-binary" - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-containers/scene"] + }, + + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/scene", + "type": "Scene" + } } ] } @@ -327,16 +332,18 @@ There are different types of fragment based on the format of the resource. The m "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/comments/c1", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/bodies/koto-body", "type": "TextualBody", "value": "Koto with a cover being carried", "language": "en", "format": "text/plain" - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-containers/canvas#xywh=6050,3220,925,1250"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/canvas#xywh=6050,3220,925,1250", + "type": "Canvas" + } } ``` @@ -358,16 +365,15 @@ The fragment example above can be expressed using a Specific Resource: "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/comments/c1", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/bodies/koto-body", "type": "TextualBody", "value": "Koto with a cover being carried", "language": "en", "format": "text/plain" - } - ], - "target": [ + }, + "target": { "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/resources/koto-sr", "type": "SpecificResource", @@ -381,7 +387,6 @@ The fragment example above can be expressed using a Specific Resource: "value": "xywh=6050,3220,925,1250" } } - ] } ``` @@ -548,7 +553,7 @@ The example demonstrates the use of the common descriptive properties [`label`][ "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/annotation/c1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://iiif.io/api/presentation/example/image/painting/full/max/0/default.jpg", "type": "Image", @@ -563,9 +568,11 @@ The example demonstrates the use of the common descriptive properties [`label`][ // etc } ] - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-containers/canvas"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-containers/canvas", + "type": "Canvas" + } } ] } @@ -640,16 +647,18 @@ This example is a Manifest with multiple Canvases, each of which represents a pa "id": "https://example.org/iiif/presentation/examples/manifest-with-book/annotation/a1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://iiif.io/api/presentation/example-content-resources/image/page1.jpg", "type": "Image", "format": "image/jpeg", "height": 4613, "width": 3204 - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-book/canvas/c1"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-book/canvas/c1", + "type": "Canvas" + } } ] } @@ -670,16 +679,18 @@ This example is a Manifest with multiple Canvases, each of which represents a pa "id": "https://example.org/iiif/presentation/examples/manifest-with-book/annotation/a2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://iiif.io/api/presentation/example-content-resources/image/page2.jpg", "type": "Image", "format": "image/jpeg", "height": 4613, "width": 3204 - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-book/canvas/c2"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-book/canvas/c2", + "type": "Canvas" + } } ] } @@ -700,16 +711,18 @@ This example is a Manifest with multiple Canvases, each of which represents a pa "id": "https://example.org/iiif/presentation/examples/manifest-with-book/annotation/a3", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://iiif.io/api/presentation/example-content-resources/image/page3.jpg", "type": "Image", "format": "image/jpeg", "height": 4613, "width": 3204 - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-book/canvas/c3"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-book/canvas/c3", + "type": "Canvas" + } } ] } @@ -826,16 +839,18 @@ Manifest for the October 27, 1881 issue, with Ranges for table of contents: "id": "https://example.org/iiif/periodical/multi-part-collection/annotation/a1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/image/page1.jpg", "type": "Image", "format": "image/jpeg", "height": 4613, "width": 3204 - } - ], - "target": ["https://example.org/iiif/periodical/multi-part-collection/canvas/c1"] + }, + "target": { + "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c1", + "type": "Canvas" + } } ] } @@ -856,16 +871,18 @@ Manifest for the October 27, 1881 issue, with Ranges for table of contents: "id": "https://example.org/iiif/periodical/multi-part-collection/annotation/a2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/image/page2.jpg", "type": "Image", "format": "image/jpeg", "height": 4613, "width": 3204 - } - ], - "target": ["https://example.org/iiif/periodical/multi-part-collection/canvas/c2"] + }, + "target": { + "id": "https://example.org/iiif/periodical/multi-part-collection/canvas/c2", + "type": "Canvas" + } } ] } @@ -945,16 +962,17 @@ This example is a Manifest with two Timelines, each of which represent a tempora "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/accompany/c1/image", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/presentation/example-content-resources/image/cover.jpg", "type": "Image", "format": "image/jpeg", "height": 900, "width": 900 - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-audio/accompany/ac1"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/accompany/c1", + "type": "Canvas" } ] } @@ -975,7 +993,7 @@ This example is a Manifest with two Timelines, each of which represent a tempora "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/annotation/a1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/presentation/example-content-resources/audio/track1.mp4", "type": "Sound", @@ -983,8 +1001,11 @@ This example is a Manifest with two Timelines, each of which represent a tempora "duration": 231, "language": ["de"] } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-audio/timeline/t1"] + + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/timeline/t1", + "type": "Timeline" + } } ] } @@ -1004,16 +1025,18 @@ This example is a Manifest with two Timelines, each of which represent a tempora "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/annotation/a2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/presentation/example-content-resources/audio/track2.mp4", "type": "Sound", "format": "audio/mp4", "duration": 230.5, "language": ["en"] - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-audio/timeline/t2"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/timeline/t2", + "type": "Timeline" + } } ] } @@ -1040,16 +1063,18 @@ This example is a Manifest with two Timelines, each of which represent a tempora "id": "https://example.org/iiif/presentation/examples/external-anno/a1", "type": "Annotation", "motivation": ["supplementing"], - "body": [ + "body": { "id": "https://example.org/presentation/example-content-resources/lyrics1.txt", "type": "TextualBody", "language": "de", "format": "text/plain", "value": "Hast du etwas Zeit für mich?" - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-audio/timeline/t1#t=3.5,6.8"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-audio/timeline/t1#t=3.5,6.8", + "type": "Timeline" + } } ] // (annotations for the rest of the song lines) @@ -1101,7 +1126,7 @@ This example is a Manifest with one Canvas that represents the temporal extent o "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/placeholder/image", "type": "Annotation", "motivation": "painting", - "body": [ + "body": { "id": "https://example.org/image/placeholder.png", "type": "Image", @@ -1109,8 +1134,10 @@ This example is a Manifest with one Canvas that represents the temporal extent o "height": 320, "width": 400 } - ], - "target": ["https://iiif.io/api/cookbook/recipe/0013-placeholderCanvas/canvas/donizetti/placeholder"] + "target": { + "id": "https://iiif.io/api/cookbook/recipe/0013-placeholderCanvas/canvas/donizetti/placeholder", + "type": "Canvas" + } } ] } @@ -1125,7 +1152,7 @@ This example is a Manifest with one Canvas that represents the temporal extent o "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/anno1", "type": "Annotation", "motivation": "painting", - "body": [ + "body": { "type": "Choice", "items": [ @@ -1150,9 +1177,11 @@ This example is a Manifest with one Canvas that represents the temporal extent o "fileSize": 1345876231 } ] - } - ], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-movie/canvas"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/canvas", + "type": "Canvas" + } } ] } @@ -1167,7 +1196,7 @@ This example is a Manifest with one Canvas that represents the temporal extent o "type": "Annotation", "motivation": "supplementing", "provides": [ "subtitles" ], - "body": [{ + "body": { "id": "https://example.org/text/subtitles.vtt", "type": "Text", "format": "text/vtt", @@ -1177,8 +1206,11 @@ This example is a Manifest with one Canvas that represents the temporal extent o ] }, "language": "en" - }], - "target": ["https://example.org/iiif/presentation/examples/manifest-with-movie/canvas"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/canvas", + "type": "Canvas" + } } ] } @@ -1270,14 +1302,16 @@ This example is a Manifest with a single Scene, with a single 3D model of a spac "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/astronaut/astronaut.glb", "type": "Model", "format": "model/gltf-binary" - } - ], - "target": ["https://example.org/iiif/scene1/page/p1/1"] + }, + "target": { + "id": "https://example.org/iiif/scene1/page/p1/1", + "type": "Scene" + } } ] } @@ -1327,14 +1361,13 @@ The Light is green and has a position, but has its default orientation of lookin "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/astronaut/astronaut.glb", "type": "Model", "format": "model/gltf-binary" - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -1348,7 +1381,6 @@ The Light is green and has a position, but has its default orientation of lookin "y": 1.0, "z": 1.0 } - ] } ] }, @@ -1356,7 +1388,7 @@ The Light is green and has a position, but has its default orientation of lookin "id": "https://example.org/iiif/3d/anno2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/iiif/3d/cameras/1", "type": "PerspectiveCamera", @@ -1368,9 +1400,8 @@ The Light is green and has a position, but has its default orientation of lookin "near": 1, "far": 100, "fieldOfView": 50 - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": @@ -1387,22 +1418,20 @@ The Light is green and has a position, but has its default orientation of lookin } ] } - ] }, { "id": "https://example.org/iiif/3d/anno2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/iiif/3d/lights/1", "type": "SpotLight", "label": { "en": ["Spot Light 1"] }, "angle": 90.0, "color": "#A0FFA0" - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -1418,7 +1447,6 @@ The Light is green and has a position, but has its default orientation of lookin } ] } - ] } ] } @@ -1465,14 +1493,13 @@ This example is a Manifest with a single Scene with multiple models painted into "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/chess/pawn.glb", "label": { "en": ["Pawn 1"] }, "type": "Model", "format": "model/gltf-binary" - } - ], + }, "target": [ { "type": "SpecificResource", @@ -1489,13 +1516,12 @@ This example is a Manifest with a single Scene with multiple models painted into } ] } - ] }, { "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "type": "SpecificResource", "source": { @@ -1518,9 +1544,8 @@ This example is a Manifest with a single Scene with multiple models painted into "z": 0.0 } ] - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -1536,14 +1561,13 @@ This example is a Manifest with a single Scene with multiple models painted into } ] } - ] }, { "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], "exclude": ["Audio", "Lights"], - "body": [ + "body": { "type": "SpecificResource", "source": { @@ -1560,9 +1584,8 @@ This example is a Manifest with a single Scene with multiple models painted into "z": 1.5 } ] - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -1578,7 +1601,6 @@ This example is a Manifest with a single Scene with multiple models painted into } ] } - ] } ] } @@ -1639,7 +1661,7 @@ In this example, the audio content resources have durations that do not match th "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/iiif/audio/1", "type": "AmbientAudio", @@ -1654,21 +1676,19 @@ In this example, the audio content resources have durations that do not match th "unit": "relative", "quantityValue": 0.1 } - } - ], - "target": [ + }, + "target": { "id": "https://example.org/iiif/scene1", "type": "Scene" } - ] }, { "id": "https://example.org/iiif/3d/anno2", "type": "Annotation", "motivation": ["painting"], "timeMode": "trim", - "body": [ + "body": { "id": "https://example.org/iiif/audio/2", "type": "PointAudio", @@ -1685,8 +1705,7 @@ In this example, the audio content resources have durations that do not match th "quantityValue": 0.2 } } - ], - "target": [ + "target": { "id": "https://example.org/iiif/selectors/anno2", "type": "SpecificResource", @@ -1709,14 +1728,13 @@ In this example, the audio content resources have durations that do not match th } ] } - ] }, { "id": "https://example.org/iiif/3d/anno3", "type": "Annotation", "motivation": ["painting"], "timeMode": "loop", - "body": [ + "body": { "id": "https://example.org/iiif/audio/3", "type": "SpotAudio", @@ -1734,14 +1752,12 @@ In this example, the audio content resources have durations that do not match th "quantityValue": 0.3 }, "lookAt": "https://example.org/iiif/scene1" - } - ], - "target": [ + }, + "target": { "id": "https://example.org/iiif/scene1#xyz=3,0,-2&t=30,60", "type": "Scene" } - ] } ], "annotations": [ @@ -1749,13 +1765,12 @@ In this example, the audio content resources have durations that do not match th "id": "https://example.org/iiif/3d/commenting", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "type": "TextualBody", "value": "This is the point when the percussion stops playing and the tuba begins playing." - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -1769,7 +1784,6 @@ In this example, the audio content resources have durations that do not match th } ] } - ] } ] } @@ -1845,13 +1859,19 @@ This example is a Manifest with a Canvas that represents two images displayed si "type": "Image", "format": "image/jpeg" }, - "target": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c2" + "target": + {"id": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c2", + "type": "Canvas" + } }, ] } ] }, - "target": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c1#xywh=0,0,300,300" + "target": {} + "id": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c1#xywh=0,0,300,300", + "type": "Canvas" + } }, { "id": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/annotation/anno2", @@ -1876,13 +1896,19 @@ This example is a Manifest with a Canvas that represents two images displayed si "type": "Image", "format": "image/jpeg" }, - "target": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c3" + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c3", + "type": "Canvas" + } }, ] } ] }, - "target": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c1#xywh=300,0,300,300" + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-composite-two-canvases/canvas/c1#xywh=300,0,300,300", + "type": "Canvas" + } } ] } @@ -1908,15 +1934,17 @@ A Timeline, Canvas, or Scene with [`duration`][prezi-40-model-duration] can only "type": "Annotation", "motivation": ["painting"], "timeMode": "loop", - "body": [ + "body": { "id": "https://example.org/iiif/presentation/examples/nesting/timeline/t1", "type": "Timeline", "label": { "en": ["Side A: 99 Luftballons"] }, "duration": 231 - } - ], - "target": ["https://example.org/iiif/presentation/examples/nesting/canvas-10minute-duration"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/nesting/canvas-10minute-duration", + "type": "Canvas" + } } ``` @@ -1944,7 +1972,7 @@ A [`PointSelector`][prezi-40-model-PointSelector] can be used to modify the poin "id": "https://example.org/iiif/presentation/examples/nesting/anno2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "type": "SpecificResource", "source": { @@ -1962,9 +1990,8 @@ A [`PointSelector`][prezi-40-model-PointSelector] can be used to modify the poin "z": -1.0 } ] - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -1980,7 +2007,6 @@ A [`PointSelector`][prezi-40-model-PointSelector] can be used to modify the poin } ] } - ] } ``` @@ -2004,13 +2030,15 @@ When a Scene is nested into another Scene, the [`backgroundColor`][prezi-40-mode "id": "https://example.org/iiif/presentation/examples/nesting/anno3", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/iiif/presentation/examples/nesting/scene/s1", "type": "Scene" - } - ], - "target": ["https://example.org/iiif/presentation/examples/nesting/scene/s2"] + }, + "target": { + "id": "https://example.org/iiif/presentation/examples/nesting/scene/s2", + "type": "Scene" + } } ``` @@ -2122,22 +2150,24 @@ This example is a Manifest with a Canvas that contains a single painting and an "type": "Image", "format": "image/jpeg" }, - "target": "https://example.org/iiif/presentation/examples/manifest-comment/canvas" + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-comment/canvas", + "type": "Canvas" + } }, { "id": "https://example.org/iiif/presentation/examples/manifest-comment/anno/2", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "id": "https://example.org/iiif/presentation/examples/manifest-comment/anno/2/person2", "type": "TextualBody", "language": "en", "format": "text/plain", "value": "Note the expressive eyes of the subject of this painting." - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": { @@ -2152,7 +2182,6 @@ This example is a Manifest with a Canvas that contains a single painting and an } ] } - ] } ] } @@ -2194,13 +2223,15 @@ In some cases it is desirable to influence the client's positioning of the comme "label": { "en": ["A 1st century Roman portait bust."] }, - "body": [ + "body": { "id": "https://example.org/iiif/scene/commenting/models/portait.gltf", "type": "Model" - } - ], - "target": ["https://example.org/iiif/scene/commenting/scene3"] + }, + "target": { + "id": "https://example.org/iiif/scene/commenting/scene3", + "type": "Scene" + } } ] } @@ -2216,7 +2247,7 @@ In some cases it is desirable to influence the client's positioning of the comme "id": "https://example.org/iiif/presentation/examples/commenting/anno/3", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "id": "https://example.org/iiif/presentation/examples/commenting/anno/3/comment1", "type": "TextualBody", @@ -2240,9 +2271,11 @@ In some cases it is desirable to influence the client's positioning of the comme } ] } - } - ], - "target": ["https://example.org/iiif/scene/commenting/scene3/sculpture"] + }, + "target": { + "id": "https://example.org/iiif/scene/commenting/scene3/sculpture", + "type": "Scene" + } } ] } @@ -2268,13 +2301,15 @@ The resource the user should be taken to is the [`body`][prezi-40-model-body] of "id": "https://example.com/annotation/p0002-link", "type": "Annotation", "motivation": "linking", - "body": [ + "body": { "id": "https://example.com/website1", "type": "Text" - } - ], - "target": ["https://example.com/canvas/p1#xywh=265,661,1260,1239"] + }, + "target": { + "id": "https://example.com/canvas/p1#xywh=265,661,1260,1239", + "type": "Canvas" + } } ``` @@ -2318,25 +2353,26 @@ This example is a light switch that can be toggled on and off using activating a "label": { "en": ["A light switch"] }, - "body": [ + "body": { "id": "https://example.org/iiif/model/models/lightswitch.gltf", "type": "Model" - } - ], - "target": "https://example.org/iiif/scene/switch/scene-1" + }, + "target": { + "id": "https://example.org/iiif/scene/switch/scene-1, + "type": "Scene" + } }, { "id": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://example.org/iiif/scene/switch/scene-1/lights/4/body", "type": "PointLight" - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": "https://example.org/iiif/scene/switch/scene-1", @@ -2346,8 +2382,7 @@ This example is a light switch that can be toggled on and off using activating a "x": 5, "y": 5, "z": 5 } ] - } - ], + }, "behavior": ["hidden"] } ] @@ -2362,13 +2397,15 @@ This example is a light switch that can be toggled on and off using activating a "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/switch-comment-0", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "type": "TextualBody", "value": "Click the switch to turn the light on or off" } - ], - "target": "https://example.org/iiif/painting-annotation/lightswitch-1" + "target": { + "id": "https://example.org/iiif/painting-annotation/lightswitch-1", + "type": "Annotation" + } }, { "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2", @@ -2707,18 +2744,18 @@ The commenting annotation now looks like this: "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth", "type": "Annotation", "motivation": ["commenting"], - "bodyValue": "Mandibular tooth", + "body": {"type": "TextualBody", "value": "Mandibular tooth"}, "scope": [ { "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth", "type": "Annotation" } ], - "target": [ + "target": { // SpecificResource with PointSelector } - ] + }, ``` From e516ed2e441628814ec4cb77730562bcebad6775 Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Tue, 17 Feb 2026 10:09:52 -0500 Subject: [PATCH 5/7] finished bodies / targets --- source/presentation/4.0/index.md | 167 +++++++++++++++---------------- 1 file changed, 83 insertions(+), 84 deletions(-) diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md index 975d4dbfe..b9653e17d 100644 --- a/source/presentation/4.0/index.md +++ b/source/presentation/4.0/index.md @@ -2411,24 +2411,30 @@ This example is a light switch that can be toggled on and off using activating a "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2", "type": "Annotation", "motivation": ["activating"], - "target": "https://example.org/iiif/painting-annotation/lightswitch-1", - "body": [ - { - "type": "SpecificResource", - "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2", - "action": ["disable"] - }, - { - "type": "SpecificResource", - "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3", - "action": ["enable"] + "target": { + "id": "https://example.org/iiif/painting-annotation/lightswitch-1", + "type": "Annotation" }, - { - "type": "SpecificResource", - "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4", - "action": ["show"] - } - ] + "body": { + "type": "List", + "items": [ + { + "type": "SpecificResource", + "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2", + "action": ["disable"] + }, + { + "type": "SpecificResource", + "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3", + "action": ["enable"] + }, + { + "type": "SpecificResource", + "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4", + "action": ["show"] + } + ] + } }, { "id": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3", @@ -2436,24 +2442,31 @@ This example is a light switch that can be toggled on and off using activating a "motivation": [ "activating" ], - "target": "https://example.org/iiif/painting-annotation/lightswitch-1", - "body": [ - { - "type": "SpecificResource", - "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3", - "action": ["disable"] - }, - { - "type": "SpecificResource", - "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4", - "action": ["hide"] + "target": { + "id": "https://example.org/iiif/painting-annotation/lightswitch-1", + "type": "Annotation" + }, + "body": { + "type": "List", + "items": + [ + { + "type": "SpecificResource", + "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-off-3", + "action": ["disable"] + }, + { + "type": "SpecificResource", + "source": "https://example.org/iiif/scene/switch/scene-1/lights/point-light-4", + "action": ["hide"] + }, + { + "type": "SpecificResource", + "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2", + "action": ["enable"] + } + ] }, - { - "type": "SpecificResource", - "source": "https://example.org/iiif/scene/switch/scene-1/annos/1/activating-on-2", - "action": ["enable"] - } - ], "behavior": ["disabled"] } ] @@ -2501,17 +2514,15 @@ The format of the `value` string is implementation-specific, and will depend on "id": "https://example.org/iiif/3d/painting-anno-for-music-box", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/music-box.glb", "type": "Model" - } - ], - "target": [ + }, + "target": { // SpecificResource with PointSelector } - ] } ], "annotations": [ @@ -2523,30 +2534,27 @@ The format of the `value` string is implementation-specific, and will depend on "id": "https://example.org/iiif/3d/box-opening-commenting-anno", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "type": "TextualBody", "value": "Click me to open the lid" - } - ], - "target": [ + }, + "target": { "id": "https://example.org/iiif/3d/painting-anno-for-music-box", "type": "Annotation" } - ] } { "id": "https://example.org/iiif/3d/box-opening-activating-anno", "type": "Annotation", "motivation": ["activating"], - "target": [ + "target": { "id": "https://example.org/iiif/3d/box-opening-commenting-anno", "type": "Annotation" - } - ], - "body": [ + }, + "body": { "type": "SpecificResource", "source": "https://example.org/iiif/3d/painting-anno-for-music-box", @@ -2558,7 +2566,6 @@ The format of the `value` string is implementation-specific, and will depend on ], "action": ["start"] } - ] } ] } @@ -2595,24 +2602,22 @@ It is possible to associate a particular camera with a particular commenting ann "id": "https://example.org/iiif/3d/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_mandible.glb", "type": "Model" - } - ], - "target": [ + }, + "target": { // SpecificResource with PointSelector } - ] }, { "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth", "type": "Annotation", "motivation": ["painting"], "behavior": ["hidden"], - "body": [ + "body": { "id": "https://example.org/iiif/3d/cameras/1", "type": "PerspectiveCamera", @@ -2620,9 +2625,8 @@ It is possible to associate a particular camera with a particular commenting ann "fieldOfView": 50.0, "near": 0.10, "far": 2000.0 - } - ], - "target": [ + }, + "target": { "type": "SpecificResource", "source": [ @@ -2638,23 +2642,20 @@ It is possible to associate a particular camera with a particular commenting ann } ] } - ] }, { "id": "https://example.org/iiif/3d/anno2", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_cranium.glb", "type": "Model" } - ], - "target": [ + "target": { // SpecificResource with PointSelector } - ] } ] } @@ -2670,51 +2671,45 @@ It is possible to associate a particular camera with a particular commenting ann "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "type": "TextualBody", "value": "Mandibular tooth" - } - ], - "target": [ + }, + "target": { // SpecificResource with PointSelector } - ] }, { "id": "https://example.org/iiif/3d/commenting-anno-for-right-pterygoid-hamulus", "type": "Annotation", "motivation": ["commenting"], - "body": [ + "body": { "type": "TextualBody", "value": "Right pterygoid hamulus" - } - ], - "target": [ + }, + "target": { // SpecificResource with PointSelector } - ] }, { "id": "https://example.org/iiif/3d/anno9", "type": "Annotation", "motivation": ["activating"], - "target": [ + "target": { "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth", "type": "Annotation" } - ], - "body": [ + "body": { "type": "SpecificResource", "source": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth", "action": ["show", "enable", "select"] } - ] } ] } @@ -2744,7 +2739,10 @@ The commenting annotation now looks like this: "id": "https://example.org/iiif/3d/commenting-anno-for-mandibular-tooth", "type": "Annotation", "motivation": ["commenting"], - "body": {"type": "TextualBody", "value": "Mandibular tooth"}, + "body": { + "type": "TextualBody", + "value": "Mandibular tooth" + }, "scope": [ { "id": "https://example.org/iiif/3d/anno-that-paints-desired-camera-to-view-tooth", @@ -2887,7 +2885,7 @@ An image might not be correctly aligned with the Canvas, and require rotation as "id": "http://example.org/iiif/book1/annotation/anno1", "type": "Annotation", "motivation": ["painting"], - "body": [ + "body": { "type": "SpecificResource", "source": { @@ -2903,14 +2901,12 @@ An image might not be correctly aligned with the Canvas, and require rotation as "type": "ImageApiSelector", "rotation": "90" } - } - ], - "target": [ + }, + "target": { "id": "http://example.org/iiif/book1/canvas/p1#xywh=50,50,320,240", "type": "Canvas" } - ] } ``` @@ -2990,7 +2986,10 @@ The value of `provides` is an array of strings, taken from the [IIIF Registry of "motivation": "supplementing", "provides": [ "alternativeText" ], "body": {...}, - "target": "https://example.org/iiif/presentation/examples/manifest-with-movie/canvas" + "target": { + "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/canvas", + "type": "Canvas" + } } ] } From d624ca02a71fd9ec7346dda86a0d7951865d6d9e Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Tue, 17 Feb 2026 10:11:32 -0500 Subject: [PATCH 6/7] motivation arrays --- source/presentation/4.0/index.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md index b9653e17d..ebafb708e 100644 --- a/source/presentation/4.0/index.md +++ b/source/presentation/4.0/index.md @@ -1125,7 +1125,7 @@ This example is a Manifest with one Canvas that represents the temporal extent o { "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/placeholder/image", "type": "Annotation", - "motivation": "painting", + "motivation": ["painting"], "body": { "id": "https://example.org/image/placeholder.png", @@ -1151,7 +1151,7 @@ This example is a Manifest with one Canvas that represents the temporal extent o { "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/anno1", "type": "Annotation", - "motivation": "painting", + "motivation": ["painting"], "body": { "type": "Choice", @@ -1194,7 +1194,7 @@ This example is a Manifest with one Canvas that represents the temporal extent o { "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/subtitles/anno", "type": "Annotation", - "motivation": "supplementing", + "motivation": ["supplementing"], "provides": [ "subtitles" ], "body": { "id": "https://example.org/text/subtitles.vtt", @@ -2300,7 +2300,7 @@ The resource the user should be taken to is the [`body`][prezi-40-model-body] of { "id": "https://example.com/annotation/p0002-link", "type": "Annotation", - "motivation": "linking", + "motivation": ["linking"], "body": { "id": "https://example.com/website1", @@ -2983,7 +2983,7 @@ The value of `provides` is an array of strings, taken from the [IIIF Registry of { "id": "https://example.org/iiif/presentation/examples/manifest-with-movie/subtitles/anno", "type": "Annotation", - "motivation": "supplementing", + "motivation": ["supplementing"], "provides": [ "alternativeText" ], "body": {...}, "target": { From 279750ca34266e9b0e1ee67e26260334a28d6f4c Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Tue, 17 Feb 2026 10:14:00 -0500 Subject: [PATCH 7/7] fix quotes --- source/presentation/4.0/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md index ebafb708e..6d8f5c81c 100644 --- a/source/presentation/4.0/index.md +++ b/source/presentation/4.0/index.md @@ -2359,7 +2359,7 @@ This example is a light switch that can be toggled on and off using activating a "type": "Model" }, "target": { - "id": "https://example.org/iiif/scene/switch/scene-1, + "id": "https://example.org/iiif/scene/switch/scene-1", "type": "Scene" } },