@projektemacher/storymapjs 0.10.8 → 0.11.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.
Files changed (195) hide show
  1. package/CHANGELOG +81 -0
  2. package/README.md +129 -12
  3. package/dist/assets/{demo-DBpeF31K.js → demo-bWnOyfUw.js} +1 -1
  4. package/dist/assets/harness-C3JUv5Ii.js +1 -0
  5. package/dist/assets/{harness-multi-CYHgI0a9.js → harness-multi-XZNex3tb.js} +1 -1
  6. package/dist/assets/{harness-support-Do7sIp2j.js → harness-support-CjfZIVeb.js} +1 -1
  7. package/dist/assets/main-DQ32hWBM.js +17 -0
  8. package/dist/context.json +13 -2
  9. package/dist/css/storymap.css +1 -1
  10. package/dist/demo.html +3 -2
  11. package/dist/docs/api/assets/navigation.js +1 -1
  12. package/dist/docs/api/assets/search.js +1 -1
  13. package/dist/docs/api/classes/StoryMap.html +777 -269
  14. package/dist/docs/api/functions/MediaType.html +1 -1
  15. package/dist/docs/api/functions/isPresentation3Collection.html +1 -1
  16. package/dist/docs/api/functions/isPresentation3Manifest.html +1 -1
  17. package/dist/docs/api/functions/isSlideshowCollection.html +51 -0
  18. package/dist/docs/api/functions/loadCSS.html +1 -1
  19. package/dist/docs/api/functions/manifestToStorymapData.html +1 -1
  20. package/dist/docs/api/functions/setLanguage.html +1 -1
  21. package/dist/docs/api/functions/slideshowToStorymapData.html +51 -0
  22. package/dist/docs/api/functions/slideshowVersion.html +48 -0
  23. package/dist/docs/api/functions/storymapToManifest.html +1 -1
  24. package/dist/docs/api/functions/validateStorymap.html +1 -1
  25. package/dist/docs/api/functions/validateStorymapAndReport.html +1 -1
  26. package/dist/docs/api/index.html +115 -12
  27. package/dist/docs/api/interfaces/AnimationHandle.html +2 -2
  28. package/dist/docs/api/interfaces/ImagereadyPayload.html +4 -4
  29. package/dist/docs/api/interfaces/LanguageEntry.html +6 -6
  30. package/dist/docs/api/interfaces/LatLngLiteral.html +4 -4
  31. package/dist/docs/api/interfaces/LoadOptions.html +2 -2
  32. package/dist/docs/api/interfaces/MapEvents.html +116 -0
  33. package/dist/docs/api/interfaces/MapMarkerEvents.html +66 -0
  34. package/dist/docs/api/interfaces/MarkerEventPayload.html +57 -0
  35. package/dist/docs/api/interfaces/MediaEvents.html +78 -0
  36. package/dist/docs/api/interfaces/MenuBarEvents.html +114 -0
  37. package/dist/docs/api/interfaces/MessageEvents.html +72 -0
  38. package/dist/docs/api/interfaces/OlLayer.html +1 -1
  39. package/dist/docs/api/interfaces/OlMap.html +1 -1
  40. package/dist/docs/api/interfaces/OlSource.html +1 -1
  41. package/dist/docs/api/interfaces/OlTileLayer.html +1 -1
  42. package/dist/docs/api/interfaces/OlVectorLayer.html +1 -1
  43. package/dist/docs/api/interfaces/OlView.html +1 -1
  44. package/dist/docs/api/interfaces/SlideBackgroundState.html +66 -0
  45. package/dist/docs/api/interfaces/SlideEvents.html +78 -0
  46. package/dist/docs/api/interfaces/SlideNavEvents.html +72 -0
  47. package/dist/docs/api/interfaces/SlideshowPlayerSettings.html +182 -0
  48. package/dist/docs/api/interfaces/SlideshowToStorymapResult.html +60 -0
  49. package/dist/docs/api/interfaces/SlideshowTranslatorOptions.html +65 -0
  50. package/dist/docs/api/interfaces/SlideshowWarning.html +72 -0
  51. package/dist/docs/api/interfaces/StoryMapEvents.html +146 -0
  52. package/dist/docs/api/interfaces/StoryMapMarker.html +763 -0
  53. package/dist/docs/api/interfaces/StorySliderEvents.html +102 -0
  54. package/dist/docs/api/interfaces/StorymapBasemap.html +69 -0
  55. package/dist/docs/api/interfaces/StorymapData.html +12 -6
  56. package/dist/docs/api/interfaces/StorymapDataWrapper.html +2 -2
  57. package/dist/docs/api/interfaces/StorymapDocument.html +2 -2
  58. package/dist/docs/api/interfaces/StorymapError.html +3 -3
  59. package/dist/docs/api/interfaces/StorymapGeoreference.html +5 -5
  60. package/dist/docs/api/interfaces/StorymapGeoreferenceBody.html +4 -4
  61. package/dist/docs/api/interfaces/StorymapGroundControlPoint.html +4 -4
  62. package/dist/docs/api/interfaces/StorymapLanguageMap.html +2 -2
  63. package/dist/docs/api/interfaces/StorymapManifest.html +12 -12
  64. package/dist/docs/api/interfaces/StorymapManifestAnnotation.html +43 -11
  65. package/dist/docs/api/interfaces/StorymapManifestBackground.html +6 -6
  66. package/dist/docs/api/interfaces/StorymapManifestCanvas.html +65 -17
  67. package/dist/docs/api/interfaces/StorymapManifestContentResource.html +8 -8
  68. package/dist/docs/api/interfaces/StorymapManifestFeatureCollection.html +4 -4
  69. package/dist/docs/api/interfaces/StorymapManifestGeoreferencing.html +7 -7
  70. package/dist/docs/api/interfaces/StorymapManifestImageService.html +4 -4
  71. package/dist/docs/api/interfaces/StorymapManifestRange.html +5 -5
  72. package/dist/docs/api/interfaces/StorymapManifestService.html +4 -4
  73. package/dist/docs/api/interfaces/StorymapManifestSpecificResource.html +4 -4
  74. package/dist/docs/api/interfaces/StorymapManifestStatement.html +3 -3
  75. package/dist/docs/api/interfaces/StorymapMapOptions.html +5 -5
  76. package/dist/docs/api/interfaces/StorymapOptions.html +277 -75
  77. package/dist/docs/api/interfaces/StorymapOverlayLayer.html +42 -11
  78. package/dist/docs/api/interfaces/StorymapSlide.html +70 -16
  79. package/dist/docs/api/interfaces/StorymapSlideBackground.html +4 -4
  80. package/dist/docs/api/interfaces/StorymapSlideLocation.html +58 -14
  81. package/dist/docs/api/interfaces/StorymapSlideMarker.html +8 -9
  82. package/dist/docs/api/interfaces/StorymapSlideMedia.html +49 -10
  83. package/dist/docs/api/interfaces/StorymapSlideNarration.html +61 -9
  84. package/dist/docs/api/interfaces/StorymapSlideText.html +4 -4
  85. package/dist/docs/api/interfaces/StorymapTilejson.html +8 -8
  86. package/dist/docs/api/interfaces/SwipableEvents.html +102 -0
  87. package/dist/docs/api/interfaces/TextEvents.html +66 -0
  88. package/dist/docs/api/media/events.md +66 -0
  89. package/dist/docs/api/media/migration-from-knightlab.md +89 -49
  90. package/dist/docs/api/media/slideshow.md +109 -0
  91. package/dist/docs/api/media/storymap-as-iiif-manifest.md +1007 -0
  92. package/dist/docs/api/modules.html +6 -6
  93. package/dist/docs/api/types/ContentState.html +3 -3
  94. package/dist/docs/api/types/FiredEvent.html +43 -0
  95. package/dist/docs/api/types/ImagereadyKind.html +1 -1
  96. package/dist/docs/api/types/MediaTypeMatch.html +5 -5
  97. package/dist/docs/api/types/SwipeDirection.html +36 -0
  98. package/dist/docs/api/types/TileSourceFactory.html +1 -1
  99. package/dist/docs/authoring.html +20 -7
  100. package/dist/docs/events.html +263 -0
  101. package/dist/docs/iiif.html +136 -22
  102. package/dist/docs/migration.html +66 -19
  103. package/dist/docs/readme.html +113 -12
  104. package/dist/embed/index.html +7 -0
  105. package/dist/examples/font-css-false.json +33 -0
  106. package/dist/examples/issue-image-region.json +1 -1
  107. package/dist/examples/layers-control.json +60 -0
  108. package/dist/examples/map-template-provider.json +36 -0
  109. package/dist/examples/multi-media.json +71 -0
  110. package/dist/examples-iiif/annotated-image.json +16 -0
  111. package/dist/examples-iiif/font-css-false.json +114 -0
  112. package/dist/examples-iiif/issue-image-region.json +1 -1
  113. package/dist/examples-iiif/layers-control.json +226 -0
  114. package/dist/examples-iiif/map-template-provider.json +133 -0
  115. package/dist/examples-iiif/multi-media.json +237 -0
  116. package/dist/examples-slideshow/single.json +79 -0
  117. package/dist/examples-slideshow/static/pixel.png +0 -0
  118. package/dist/examples-slideshow/static.json +44 -0
  119. package/dist/harness-multi.html +3 -3
  120. package/dist/harness.html +4 -3
  121. package/dist/index.html +3 -2
  122. package/dist/js/storymap.d.ts +1326 -289
  123. package/dist/js/storymap.js +6690 -4784
  124. package/dist/js/storymap.js.map +1 -1
  125. package/dist/navplace-properties.json +14 -0
  126. package/dist/site.css +54 -36
  127. package/docs/migration-from-knightlab.md +89 -49
  128. package/docs/storymap-as-iiif-manifest.md +199 -126
  129. package/package.json +4 -2
  130. package/schema/storymap.schema.json +334 -34
  131. package/src/core/Util.ts +3 -1
  132. package/src/core/mixins.ts +42 -28
  133. package/src/language/Language.ts +7 -0
  134. package/src/language/locale/.expected-gaps.json +287 -27
  135. package/src/language/locale/de.json +11 -1
  136. package/src/language/locale/en.json +11 -1
  137. package/src/main.ts +51 -0
  138. package/src/map/Map.ts +44 -6
  139. package/src/map/MapMarker.ts +16 -3
  140. package/src/map/openlayers/Map.OpenLayers.ts +787 -62
  141. package/src/map/openlayers/MapMarker.OpenLayers.ts +113 -13
  142. package/src/map/slideView.ts +149 -0
  143. package/src/map/types.ts +2 -0
  144. package/src/media/EmbedUtil.ts +27 -2
  145. package/src/media/Media.ts +27 -4
  146. package/src/media/embedId.ts +6 -0
  147. package/src/media/types/Flickr.ts +14 -3
  148. package/src/media/types/HtmlMedia.ts +66 -0
  149. package/src/media/types/Image.ts +15 -3
  150. package/src/media/types/SoundCloud.ts +1 -1
  151. package/src/media/types/Text.ts +27 -8
  152. package/src/media/types/Twitter.ts +9 -7
  153. package/src/media/types/Vimeo.ts +1 -1
  154. package/src/media/types/YouTube.ts +2 -2
  155. package/src/scss/Typography.scss +15 -15
  156. package/src/scss/VCO.StoryMap.scss +173 -8
  157. package/src/scss/core/Reset.scss +5 -18
  158. package/src/scss/map/VCO.Map.scss +1 -1
  159. package/src/scss/map/VCO.MapMarker.scss +20 -9
  160. package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +7 -4
  161. package/src/scss/media/VCO.Media.scss +7 -7
  162. package/src/scss/media/types/VCO.Media.Blockquote.scss +1 -1
  163. package/src/scss/media/types/VCO.Media.Text.scss +5 -5
  164. package/src/scss/media/types/VCO.Media.Twitter.scss +4 -4
  165. package/src/scss/media/types/VCO.Media.Wikipedia.scss +2 -19
  166. package/src/scss/site/site.scss +55 -36
  167. package/src/scss/slider/VCO.Slide.scss +49 -11
  168. package/src/scss/slider/VCO.SlideNav.scss +23 -7
  169. package/src/scss/slider/VCO.StorySlider.scss +50 -0
  170. package/src/scss/snapmap/VCO.SnapMap.scss +3 -3
  171. package/src/scss/ui/VCO.Consent.scss +20 -14
  172. package/src/scss/ui/VCO.Layers.scss +119 -0
  173. package/src/scss/ui/VCO.MenuBar.Button.scss +140 -19
  174. package/src/scss/ui/VCO.MenuBar.scss +9 -2
  175. package/src/scss/ui/VCO.Message.scss +14 -0
  176. package/src/slider/Slide.ts +232 -74
  177. package/src/slider/SlideNav.ts +15 -4
  178. package/src/slider/StorySlider.ts +203 -22
  179. package/src/storymap/Consent.ts +22 -0
  180. package/src/storymap/StoryMap.ts +944 -131
  181. package/src/storymap/content-state.ts +3 -8
  182. package/src/storymap/font-css.ts +72 -0
  183. package/src/storymap/from-slideshow.ts +785 -0
  184. package/src/storymap/iiif-shared.ts +228 -0
  185. package/src/storymap/iiif.ts +289 -100
  186. package/src/storymap/to-iiif.ts +131 -44
  187. package/src/types.ts +382 -17
  188. package/src/ui/LayersControl.ts +302 -0
  189. package/src/ui/MenuBar.ts +232 -21
  190. package/src/ui/Message.ts +36 -3
  191. package/src/ui/Swipable.ts +25 -7
  192. package/dist/assets/harness-Cr0rYpvt.js +0 -1
  193. package/dist/assets/main-DXalctuR.js +0 -17
  194. package/src/scss/VCO.StoryMap.Dark.scss +0 -150
  195. package/src/scss/Variables.Dark.scss +0 -57
@@ -10,7 +10,11 @@ the fixtures in [`public/examples/`](../public/examples/) are real-world samples
10
10
  ([`public/examples-iiif/`](../public/examples-iiif/)), and
11
11
  `scripts/validate-iiif.mjs` checks every converted manifest against the
12
12
  [official IIIF presentation validator](https://presentation-validator.iiif.io/)
13
- (`npm run validate:iiif`). All converted fixtures pass the official validator.
13
+ (`npm run validate:iiif`). All converted fixtures pass the official validator,
14
+ except the two hand-authored georeferenced-layer fixtures, which the base
15
+ validator schema cannot accept by design (see "Geo-referenced layers" below);
16
+ `npm run validate:iiif` reports those two as _not covered_ rather than as
17
+ failures.
14
18
 
15
19
  ## Contexts
16
20
 
@@ -28,7 +32,6 @@ reference; a manifest must reference it by URL, not paste it in (see the
28
32
  "@version": 1.1,
29
33
  "storymap": "https://christianmahnke.de/iiif/storymap#",
30
34
  "mapAsImage": "storymap:mapAsImage",
31
- "basemap": "storymap:basemap",
32
35
  "tilejson": "storymap:tilejson",
33
36
  "mapAccessToken": "storymap:mapAccessToken",
34
37
  "mapBackgroundColor": "storymap:mapBackgroundColor",
@@ -58,7 +61,19 @@ reference; a manifest must reference it by URL, not paste it in (see the
58
61
  "@type": "@id"
59
62
  },
60
63
  "mediaSrcset": "storymap:mediaSrcset",
61
- "mediaSizes": "storymap:mediaSizes"
64
+ "mediaSizes": "storymap:mediaSizes",
65
+ "rotation": "storymap:rotation",
66
+ "basemap": "storymap:basemap",
67
+ "filter": "storymap:filter",
68
+ "mask": "storymap:mask",
69
+ "slidetimeout": "storymap:slidetimeout",
70
+ "imgoverlay": "storymap:imgoverlay",
71
+ "loop": "storymap:loop",
72
+ "offset": "storymap:offset",
73
+ "play": "storymap:play",
74
+ "stopOnExit": "storymap:stopOnExit",
75
+ "stopAllPrevious": "storymap:stopAllPrevious",
76
+ "provenance": "storymap:provenance"
62
77
  }
63
78
  }
64
79
  ```
@@ -94,7 +109,6 @@ what the fixtures reference. Content:
94
109
  "@context": {
95
110
  "@version": 1.1,
96
111
  "storymap": "https://christianmahnke.de/iiif/storymap#",
97
- "basemap": "storymap:basemap",
98
112
  "tilejson": "storymap:tilejson",
99
113
  "mapAsImage": "storymap:mapAsImage",
100
114
  "mapAccessToken": "storymap:mapAccessToken",
@@ -122,7 +136,19 @@ what the fixtures reference. Content:
122
136
  "overlays": "storymap:overlays",
123
137
  "type": { "@id": "storymap:type", "@type": "@id" },
124
138
  "mediaSrcset": "storymap:mediaSrcset",
125
- "mediaSizes": "storymap:mediaSizes"
139
+ "mediaSizes": "storymap:mediaSizes",
140
+ "rotation": "storymap:rotation",
141
+ "basemap": "storymap:basemap",
142
+ "filter": "storymap:filter",
143
+ "mask": "storymap:mask",
144
+ "slidetimeout": "storymap:slidetimeout",
145
+ "imgoverlay": "storymap:imgoverlay",
146
+ "loop": "storymap:loop",
147
+ "offset": "storymap:offset",
148
+ "play": "storymap:play",
149
+ "stopOnExit": "storymap:stopOnExit",
150
+ "stopAllPrevious": "storymap:stopAllPrevious",
151
+ "provenance": "storymap:provenance"
126
152
  }
127
153
  }
128
154
  ```
@@ -175,9 +201,16 @@ with one GeoJSON Feature:
175
201
  verbatim. For image-map storymaps (`storymap:mapAsImage: true`) the values are
176
202
  image coordinates rather than WGS84 degrees; consumers can detect this via
177
203
  `storymap:mapAsImage`.
178
- - `properties`: marker data — `name`, `zoom`, `line`, `icon`, `iconSize`,
179
- `image`, `use_custom_marker`, plus the presentation-only `popup` and
180
- `audioBadge` (only present keys).
204
+ - `properties`: marker data — `name`, `zoom`, `rotation` (view rotation in
205
+ degrees clockwise), `basemap` (a per-slide basemap override: any `map_type`
206
+ value or IIIF `info.json` URL), `filter` (per-slide image grading:
207
+ `brightness`/`contrast`/`saturate` in percent, `hueRotate` in degrees,
208
+ `sepia` in percent, `blur` in CSS pixels), `mask` (a spotlight mask:
209
+ normalized `{x, y, w, h}` viewport fractions plus `color`/`invert`), `line`,
210
+ `icon`, `iconSize`, `image`, `use_custom_marker`, plus the
211
+ presentation-only `popup` and `audioBadge` (only present keys). Slides
212
+ without `lat`/`lon` carry `rotation`/`basemap`/`filter`/`mask` as the
213
+ canvas `storymap:` terms below instead.
181
214
  - `location.use_custom_marker` / `use_custom_markers` (manifest) opt into
182
215
  custom marker rendering; see the storymap terms below.
183
216
 
@@ -189,8 +222,7 @@ context, and a client that meets a property it does not understand must ignore
189
222
  it. There is no IIIF extension for marker presentation — navPlace defines
190
223
  exactly one term, `navPlace` itself — so the local context is the only option.
191
224
  It is why `popup` and `audioBadge` need no `storymap:` term of their own, and
192
- the same mechanism is what `docs/plans/iiif-media-tours.md` §2 wants for its
193
- marker config. The nine local names hang off this project's existing namespace
225
+ the same mechanism serves marker config. The thirteen local names hang off this project's existing namespace
194
226
  (`https://christianmahnke.de/iiif/storymap#`), not a new one.
195
227
 
196
228
  ### Context order matters
@@ -307,7 +339,9 @@ properties):
307
339
  A keyword basemap and a tile URL template are different kinds of thing, and
308
340
  `mapType` used to be both. They are now separate: `storymap:basemap` names a
309
341
  source the viewer knows how to configure, and an **unprefixed** `tilejson`
310
- object describes any other tile service in the standard's own terms. Only
342
+ object describes any other tile service in the standard's own terms (the
343
+ `tilejson` context entry stays prefixed by JSON-LD convention; only the
344
+ unprefixed wire form is read). Only
311
345
  `tiles` is required:
312
346
 
313
347
  ```json
@@ -334,7 +368,9 @@ object describes any other tile service in the standard's own terms. Only
334
368
 
335
369
  `tiles` becomes `map_type`, so everything that dispatches on a template (the
336
370
  `tile_source_factory` option, attribution, the minimap) works unchanged. The
337
- rest is honoured where the map can act on it:
371
+ rest is honoured where the map can act on it when _reading_ a manifest; note
372
+ the converter only writes `{tiles}` back out, so a manifest → storymap →
373
+ manifest cycle drops `minzoom`/`maxzoom`/`bounds`/`scheme`/`center`:
338
374
 
339
375
  | Member | Effect |
340
376
  | --------- | ------------------------------------------------------------------------- |
@@ -349,45 +385,53 @@ The `center` is the initial view only, and `bounds` constrains the center
349
385
  without pinning the resolution — a hard extent constraint would fight the panel
350
386
  offset, the same reason `map_bbox` works the way it does.
351
387
 
352
- | Service property (storymap:) | StoryMap field | Values |
353
- | ----------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
354
- | `basemap` | `map_type` | A keyword the viewer configures itself: `osm:standard`, `mapbox://styles/...`, `stadia:...`, `iiif`. `zoomify` is replaced by `iiif` |
355
- | _(unprefixed)_ `tilejson` | `map_type` + `tilejson` | TileJSON 2.1 for an arbitrary tile service — see below |
356
- | `mapAsImage` | `map_as_image` | `true` when the image itself is the map |
357
- | `mapAccessToken` | `map_access_token` | Mapbox/Stadia token from the storymap data, never the repository |
358
- | `mapBackgroundColor` | `map_background_color` | CSS color |
359
- | `mapCenterOffset` | `map_center_offset` | `{left, top}` |
360
- | `mapSubdomains` | `map_subdomains` | Tile URL subdomains |
361
- | _(none)_ | `iiif.url` | From the Image API `service[]` a painting body carries, plus `/info.json`; see below |
362
- | `fontCss` | `font_css` | e.g. `stock:dancing-ledger` |
363
- | `callToAction` | `call_to_action` | boolean |
364
- | `callToActionText` | `call_to_action_text` | string |
365
- | `startAtSlide` | `start_at_slide` | 0-based slide index |
366
- | `language` | `language` | IETF language tag |
367
- | `calculateZoom` | `calculate_zoom` | boolean |
368
- | `lessBounce` | `less_bounce` | boolean |
369
- | `lineFollowsPath` | `line_follows_path` | boolean |
370
- | `showLines` | `show_lines` | boolean |
371
- | `showHistoryLine` | `show_history_line` | boolean |
372
- | `lineColor` | `line_color` | CSS color |
373
- | `lineColorInactive` | `line_color_inactive` | CSS color |
374
- | `lineWeight` | `line_weight` | number (px) |
375
- | `lineOpacity` | `line_opacity` | 0–1 |
376
- | `lineDash` | `line_dash` | CSS dash pattern |
377
- | `lineJoin` | `line_join` | CSS line join |
378
- | `useCustomMarkers` | `use_custom_markers` | boolean |
379
- | `mapArea` | `map_area` | `"full"` (default) or `"left"` |
380
- | `overviewExtent` | `overview_extent` | `[west, south, east, north]` lon/lat box for the minimap overview |
381
- | `keyboard` | `keyboard` | boolean: arrow keys navigate the story from anywhere |
382
- | `overlays` | `overlays` | array of stacked layers (see below) |
383
- | _(georeferencing annotation)_ | `overlays[]` (georeference entries) | IIIF images placed from ground control points — see "Geo-referenced layers" |
388
+ | Service property (storymap:) | StoryMap field | Values |
389
+ | ----------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
390
+ | `basemap` | `map_type` | A keyword the viewer configures itself: `osm:standard`, `mapbox://styles/...`, `stadia:...`, `iiif`. `zoomify` is replaced by `iiif` |
391
+ | _(unprefixed)_ `tilejson` | `map_type` + `tilejson` | TileJSON 2.1 for an arbitrary tile service — see below |
392
+ | `mapAsImage` | `map_as_image` | `true` when the image itself is the map |
393
+ | `mapAccessToken` | `map_access_token` | Mapbox/Stadia token from the storymap data, never the repository |
394
+ | `mapBackgroundColor` | `map_background_color` | CSS color |
395
+ | `mapCenterOffset` | `map_center_offset` | `{left, top}` |
396
+ | _(none — removed)_ | `map_subdomains` | _dropped_ (inert, no reader; see the full mapping table) |
397
+ | _(none)_ | `iiif.url` | From the Image API `service[]` a painting body carries, plus `/info.json`; see below |
398
+ | `fontCss` | `font_css` | e.g. `stock:dancing-ledger`, or `false` for no injected theme |
399
+ | `callToAction` | `call_to_action` | boolean |
400
+ | `callToActionText` | `call_to_action_text` | string |
401
+ | `startAtSlide` | `start_at_slide` | 0-based slide index |
402
+ | `language` | `language` | IETF language tag |
403
+ | `calculateZoom` | `calculate_zoom` | boolean |
404
+ | _(none — removed)_ | `less_bounce` | _dropped_ (inert, no reader; see the full mapping table) |
405
+ | `lineFollowsPath` | `line_follows_path` | boolean |
406
+ | `showLines` | `show_lines` | boolean |
407
+ | `showHistoryLine` | `show_history_line` | boolean |
408
+ | `lineColor` | `line_color` | CSS color |
409
+ | `lineColorInactive` | `line_color_inactive` | CSS color |
410
+ | `lineWeight` | `line_weight` | number (px) |
411
+ | `lineOpacity` | `line_opacity` | 0–1 |
412
+ | `lineDash` | `line_dash` | CSS dash pattern |
413
+ | `lineJoin` | `line_join` | CSS line join |
414
+ | `useCustomMarkers` | `use_custom_markers` | boolean |
415
+ | `mapArea` | `map_area` | `"full"` (default) or `"left"` |
416
+ | `overviewExtent` | `overview_extent` | `[west, south, east, north]` lon/lat box for the minimap overview |
417
+ | `keyboard` | `keyboard` | boolean: arrow keys navigate the story from anywhere |
418
+ | `overlays` | `overlays` | array of stacked layers (see below) |
419
+ | _(georeferencing annotation)_ | `overlays[]` (georeference entries) | IIIF images placed from ground control points — see "Geo-referenced layers" |
420
+ | _(viewer option)_ | `show_layers_control`, `basemaps` | the layer switcher and its basemap list: viewer-side only, never read from a manifest; `label` functions likewise never cross the JSON boundary |
384
421
 
385
422
  ### Canvas level — direct properties
386
423
 
387
424
  Canvas objects are open for extension terms, so slide-specific StoryMap data is
388
425
  carried directly on the Canvas: `storymap:type`, plus the two terms with no
389
426
  standard home, `storymap:mediaSrcset` and `storymap:mediaSizes` (see the
390
- Canvas table above). A slide's date is the standard `navDate` and its
427
+ Canvas table above), plus the view directives `storymap:rotation`,
428
+ `storymap:basemap`, `storymap:filter` and `storymap:mask` (the fallback for
429
+ slides without `lat`/`lon`, which have no `navPlace` to carry them — the
430
+ reader prefers `navPlace` when both spell a key), the per-slide autoplay
431
+ dwell `storymap:slidetimeout` (milliseconds, `0` holds), the per-slide
432
+ image overlay `storymap:imgoverlay` (`{url, size?, opacity?, extent?}`) and
433
+ the provenance identifiers `storymap:provenance`
434
+ (`{manifest?, canvas?, image?}`, data-only). A slide's date is the standard `navDate` and its
391
435
  background is the standard `background` annotation. The media caption, credit and alt
392
436
  text are **not** terms any more: they are the painting annotation's own `label`,
393
437
  `requiredStatement` and `accessibilitySummary`, which is where Presentation 3
@@ -398,6 +442,22 @@ Readers must use the prefixed term for the slide type (`storymap:type`): the
398
442
  bare `type` key of a Canvas is the IIIF class type (`"Canvas"`) and can never
399
443
  carry the StoryMap slide type.
400
444
 
445
+ **Gating.** The slideshow-motivated fields above (`rotation`, `basemap`,
446
+ `filter`, `mask`, `slidetimeout`, `imgoverlay`, `provenance`) are read
447
+ data-preservingly from any manifest, but they render **only for slideshow
448
+ tours** (the viewer's internal `slideshow_source` marker, set when a
449
+ document arrives through the slideshow translator). Hand-written manifests
450
+ and storymap JSON keep the long-standing rendering; see the README's
451
+ slideshow section. The playback flags (`storymap:loop/offset/play/
452
+ stopOnExit/stopAllPrevious`) are gated the same way.
453
+
454
+ **Placement.** The view directives live on the **Canvas** (direct
455
+ properties); the playback flags live as **Annotation** foreign members —
456
+ `storymap:loop/offset/play/stopOnExit` on the painting annotation (for
457
+ audio/video media) and the full set including `storymap:stopAllPrevious`
458
+ on the `supplementing` narration annotation. When a key is spelled both on
459
+ the Canvas and in `navPlace` properties, `navPlace` wins.
460
+
401
461
  ## Annotation-driven tour stops
402
462
 
403
463
  A Canvas annotation whose `motivation` is `commenting`, `tagging`,
@@ -427,15 +487,15 @@ The painting annotation's body is read into one shared record. The
427
487
  dropped — a manifest still using them loads, but the strings are not read —
428
488
  and the standard properties are the only source:
429
489
 
430
- | Body property | Slide media field |
431
- | --------------------------------------------------------------- | -------------------------------- |
432
- | `label` | `caption` |
433
- | `requiredStatement` (one `{label, value}` object) or `provider` | `credit` |
434
- | `accessibilitySummary` | `alt` |
435
- | `thumbnail` | `thumb` |
436
- | `type`, `format` | player selection (`MediaType()`) |
437
- | `duration`, `start`, `end` | time-anchored stops |
438
- | a sibling `TextualBody` with `format: text/vtt` | `subtitles` |
490
+ | Body property | Slide media field |
491
+ | --------------------------------------------------------------- | --------------------------------------------------------------- |
492
+ | `label` | `caption` |
493
+ | `requiredStatement` (one `{label, value}` object) or `provider` | `credit` |
494
+ | `accessibilitySummary` | `alt` |
495
+ | `thumbnail` | `thumb` |
496
+ | `type`, `format` | player selection (`MediaType()`) |
497
+ | `duration`, `start`, `end` | time-anchored stops |
498
+ | a sibling `TextualBody` with `format: text/vtt` **and an `id`** | `subtitles` (both required — the `id` is the subtitle file URL) |
439
499
 
440
500
  ## Native IIIF vs. the StoryMap extension
441
501
 
@@ -840,78 +900,91 @@ photo, and a slide with a YouTube video — full manifest:
840
900
 
841
901
  ## Full mapping table
842
902
 
843
- | Legacy field (storymap root) | IIIF path |
844
- | ---------------------------- | ----------------------------------------------------------------------- |
845
- | `slides` | `items[]` (Canvas per slide) |
846
- | `language` | `service[0].storymap:language` |
847
- | `map_type` | `service[0].storymap:basemap` (`zoomify` → `iiif`), or `tilejson.tiles` |
848
- | `map_as_image` | `service[0].storymap:mapAsImage` |
849
- | `map_mini` | _dropped_ (viewer setting, not part of the exchange format) |
850
- | `map_subdomains` | _dropped_ (inert, no reader) |
851
- | `map_access_token` | `service[0].storymap:mapAccessToken` |
852
- | `map_background_color` | `service[0].storymap:mapBackgroundColor` |
853
- | `map_center_offset` | `service[0].storymap:mapCenterOffset` |
854
- | `map_popup` | _dropped_ (viewer setting) |
855
- | `use_custom_markers` | `service[0].storymap:useCustomMarkers` |
856
- | `map_area` | `service[0].storymap:mapArea` |
857
- | `overview_extent` | `service[0].storymap:overviewExtent` |
858
- | `keyboard` | `service[0].storymap:keyboard` |
859
- | `overlays` (georeference) | Georeferencing annotation `target` + `body` |
860
- | `zoom_distance` | _dropped_ (viewer setting) |
861
- | `calculate_zoom` | `service[0].storymap:calculateZoom` |
862
- | `less_bounce` | _dropped_ (inert, no reader) |
863
- | `line_follows_path` | `service[0].storymap:lineFollowsPath` |
864
- | `show_lines` | `service[0].storymap:showLines` |
865
- | `show_history_line` | `service[0].storymap:showHistoryLine` |
866
- | `line_color` | `service[0].storymap:lineColor` |
867
- | `line_color_inactive` | `service[0].storymap:lineColorInactive` |
868
- | `line_weight` | `service[0].storymap:lineWeight` |
869
- | `line_opacity` | `service[0].storymap:lineOpacity` |
870
- | `line_dash` | `service[0].storymap:lineDash` |
871
- | `line_join` | `service[0].storymap:lineJoin` |
872
- | `iiif.url` | Canvas Image annotation `service[0].id` + `/info.json` |
873
- | `iiif.attribution` | `requiredStatement` |
874
- | `zoomify` | _dropped_ (zoomify is replaced by the IIIF reference image) |
875
- | `font_css` | `service[0].storymap:fontCss` |
876
- | `call_to_action` | `service[0].storymap:callToAction` |
877
- | `call_to_action_text` | `service[0].storymap:callToActionText` |
878
- | `relative_date` | _dropped_ (viewer setting) |
879
- | `start_at_slide` | `service[0].storymap:startAtSlide` |
880
- | _(root) `width`, `height`_ | _dropped_ (viewer embed size) |
881
-
882
- | Legacy field (slide) | IIIF path |
883
- | ------------------------------ | --------------------------------------------------------------------------- |
884
- | `type: "overview"` | Canvas `storymap:type: "overview"` |
885
- | `date` | Canvas `navDate` |
886
- | `text.headline` | Canvas `label` (language map) |
887
- | `text.text` | Canvas `summary` (language map) |
888
- | `location.lat`, `location.lon` | Canvas `navPlace` Feature `geometry.coordinates` |
889
- | `location.zoom` | Canvas `navPlace` Feature `properties.zoom` |
890
- | `location.line` | Canvas `navPlace` Feature `properties.line` |
891
- | `location.name` | Canvas `navPlace` Feature `properties.name` |
892
- | `location.icon` | Canvas `navPlace` Feature `properties.icon` |
893
- | `location.iconSize` | Canvas `navPlace` Feature `properties.iconSize` |
894
- | `location.image` | Canvas `navPlace` Feature `properties.image` |
895
- | `location.use_custom_marker` | Canvas `navPlace` Feature `properties.use_custom_marker` |
896
- | `media.url` (image) | Annotation body `{type: "Image", format: ...}` |
897
- | `media.url` (video service) | Annotation body `{type: "Video"}` |
898
- | `media.url` (audio service) | Annotation body `{type: "Sound"}` |
899
- | `media.url` (web page) | Annotation body `{type: "Text", format: "text/html"}` |
900
- | `media.url` (absent / HTML) | Annotation body `{type: "TextualBody", value: ...}` |
901
- | `media.caption` | Painting annotation `label` |
902
- | `media.credit` | Painting annotation `requiredStatement` (`{label, value}`) |
903
- | `media.alt` | Painting annotation `accessibilitySummary` |
904
- | `media.srcset` | Canvas `storymap:mediaSrcset` |
905
- | `media.sizes` | Canvas `storymap:mediaSizes` |
906
- | `location.region` | Painting annotation target `ImageApiSelector` `xywh=pixel:` |
907
- | `media.thumb` | Canvas `thumbnail[]` or the body `thumbnail[]` |
908
- | `background` | Canvas `background` painting annotation (Image + Color body) |
909
- | `uniqueid` | Canvas `id` |
910
- | `group` | A `structures` Range label; the Range order is the slide order |
911
- | `language` (per slide) | The language tag the slide's text was read in (§3.4) |
912
- | `logo`, `metadata` | Read into `data.logo` / `data.metadata[]` |
913
- | `tilejson` | `service[0].tilejson` |
914
- | `title` | Manifest `label` (a label is required, so the converter uses the file name) |
903
+ | Legacy field (storymap root) | IIIF path |
904
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
905
+ | `slides` | `items[]` (Canvas per slide) |
906
+ | `language` | `service[0].storymap:language` |
907
+ | `map_type` | `service[0].storymap:basemap` (`zoomify` → `iiif`), or `tilejson.tiles` |
908
+ | `map_as_image` | `service[0].storymap:mapAsImage` |
909
+ | `map_mini` | _dropped_ (viewer setting, not part of the exchange format) |
910
+ | `map_subdomains` | _dropped_ (inert, no reader) |
911
+ | `map_access_token` | `service[0].storymap:mapAccessToken` |
912
+ | `map_background_color` | `service[0].storymap:mapBackgroundColor` |
913
+ | `map_center_offset` | `service[0].storymap:mapCenterOffset` |
914
+ | `map_popup` | _dropped_ (viewer setting) |
915
+ | `use_custom_markers` | `service[0].storymap:useCustomMarkers` |
916
+ | `map_area` | `service[0].storymap:mapArea` |
917
+ | `overview_extent` | `service[0].storymap:overviewExtent` |
918
+ | `keyboard` | `service[0].storymap:keyboard` |
919
+ | `overlays` (georeference) | Georeferencing annotation `target` + `body` |
920
+ | `zoom_distance` | _dropped_ (viewer setting) |
921
+ | `calculate_zoom` | `service[0].storymap:calculateZoom` |
922
+ | `less_bounce` | _dropped_ (inert, no reader) |
923
+ | `line_follows_path` | `service[0].storymap:lineFollowsPath` |
924
+ | `show_lines` | `service[0].storymap:showLines` |
925
+ | `show_history_line` | `service[0].storymap:showHistoryLine` |
926
+ | `line_color` | `service[0].storymap:lineColor` |
927
+ | `line_color_inactive` | `service[0].storymap:lineColorInactive` |
928
+ | `line_weight` | `service[0].storymap:lineWeight` |
929
+ | `line_opacity` | `service[0].storymap:lineOpacity` |
930
+ | `line_dash` | `service[0].storymap:lineDash` |
931
+ | `line_join` | `service[0].storymap:lineJoin` |
932
+ | `iiif.url` | Canvas Image annotation `service[0].id` + `/info.json` (only when the story uses `map_type: "iiif"`) |
933
+ | `iiif.attribution` | `requiredStatement` |
934
+ | `zoomify` | _dropped_ (zoomify is replaced by the IIIF reference image) |
935
+ | `font_css` | `service[0].storymap:fontCss` (`false` disables the injected theme) |
936
+ | `call_to_action` | `service[0].storymap:callToAction` |
937
+ | `call_to_action_text` | `service[0].storymap:callToActionText` |
938
+ | `relative_date` | _dropped_ (viewer setting) |
939
+ | `start_at_slide` | `service[0].storymap:startAtSlide` |
940
+ | _(root) `width`, `height`_ | _dropped_ (viewer embed size) |
941
+ | _(slideshow tours) player chrome (`textmode`, `textsize`, `progressbar`, `fxmode`, `mode`, `hud*`, `shownav`, `show_*`, `viewerheight`, `autoplay`)_ | _dropped_ (no IIIF vocabulary; translator-only, see docs/slideshow.md) |
942
+ | `credit.creator` / `credit.rights` | Manifest `metadata` entries ("Creator" / "Rights") — one way: the reader keeps all metadata in `data.metadata[]` and never reconstructs `credit`, and `credit.licenseUrl` is not written at all |
943
+ | `iiif.fallbackUrl` | _dropped_ (runtime fallback; tour documents carry `image_static` per stop) |
944
+
945
+ | Legacy field (slide) | IIIF path |
946
+ | ------------------------------------------------------- | -------------------------------------------------------------------------------- |
947
+ | `type: "overview"` | Canvas `storymap:type: "overview"` |
948
+ | `date` | Canvas `navDate` |
949
+ | `text.headline` | Canvas `label` (language map) |
950
+ | `text.text` | Canvas `summary` (language map) |
951
+ | `location.lat`, `location.lon` | Canvas `navPlace` Feature `geometry.coordinates` |
952
+ | `location.zoom` | Canvas `navPlace` Feature `properties.zoom` |
953
+ | `location.line` | Canvas `navPlace` Feature `properties.line` |
954
+ | `location.name` | Canvas `navPlace` Feature `properties.name` |
955
+ | `location.icon` | Canvas `navPlace` Feature `properties.icon` |
956
+ | `location.iconSize` | Canvas `navPlace` Feature `properties.iconSize` |
957
+ | `location.image` | Canvas `navPlace` Feature `properties.image` |
958
+ | `location.use_custom_marker` | Canvas `navPlace` Feature `properties.use_custom_marker` |
959
+ | `location.rotation` | Canvas `navPlace` Feature `properties.rotation`, else Canvas `storymap:rotation` |
960
+ | `location.basemap` | Canvas `navPlace` Feature `properties.basemap`, else Canvas `storymap:basemap` |
961
+ | `location.filter` | Canvas `navPlace` Feature `properties.filter`, else Canvas `storymap:filter` |
962
+ | `location.mask` | Canvas `navPlace` Feature `properties.mask`, else Canvas `storymap:mask` |
963
+ | `slidetimeout` | Canvas `storymap:slidetimeout` (milliseconds, `0` holds) |
964
+ | `imgoverlay` | Canvas `storymap:imgoverlay` |
965
+ | `provenance` | Canvas `storymap:provenance` (data-only identifiers) |
966
+ | `narration.url` | Supplementing annotation body `{type: "Sound"}` |
967
+ | `narration.loop/offset/play/stopOnExit/stopAllPrevious` | Supplementing annotation `storymap:` members (foreign members, only when set) |
968
+ | `media.offset/loop/play/stopOnExit` | Painting annotation `storymap:` members (foreign members, only when set) |
969
+ | `media.url` (image) | Annotation body `{type: "Image", format: ...}` |
970
+ | `media.url` (video service) | Annotation body `{type: "Video"}` |
971
+ | `media.url` (audio service) | Annotation body `{type: "Sound"}` |
972
+ | `media.url` (web page) | Annotation body `{type: "Text", format: "text/html"}` |
973
+ | `media.url` (absent / HTML) | Annotation body `{type: "TextualBody", value: ...}` |
974
+ | `media.caption` | Painting annotation `label` |
975
+ | `media.credit` | Painting annotation `requiredStatement` (`{label, value}`) |
976
+ | `media.alt` | Painting annotation `accessibilitySummary` |
977
+ | `media.srcset` | Canvas `storymap:mediaSrcset` |
978
+ | `media.sizes` | Canvas `storymap:mediaSizes` |
979
+ | `location.region` | Painting annotation target `ImageApiSelector` `xywh=pixel:` |
980
+ | `media.thumb` | Canvas `thumbnail[]` or the body `thumbnail[]` |
981
+ | `background` | Canvas `background` painting annotation (Image + Color body) |
982
+ | `uniqueid` | Canvas `id` |
983
+ | `group` | A `structures` Range label; the Range order is the slide order |
984
+ | `language` (per slide) | The language tag the slide's text was read in (§3.4) |
985
+ | `logo`, `metadata` | Read into `data.logo` / `data.metadata[]` |
986
+ | `tilejson` | `service[0].tilejson` |
987
+ | `title` | Manifest `label` (a label is required, so the converter uses the file name) |
915
988
 
916
989
  ## Conversion
917
990
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@projektemacher/storymapjs",
3
- "version": "0.10.8",
4
- "description": "StoryMapJS viewer library \u2014 unofficial TypeScript/OpenLayers rewrite of the Knight Lab StoryMapJS (viewer only)",
3
+ "version": "0.11.0",
4
+ "description": "StoryMapJS viewer library — unofficial TypeScript/OpenLayers rewrite of the Knight Lab StoryMapJS (viewer only)",
5
5
  "license": "MPL-2.0",
6
6
  "type": "module",
7
7
  "types": "./dist/js/storymap.d.ts",
@@ -44,6 +44,7 @@
44
44
  "ol-mapbox-style": "^13.5.1"
45
45
  },
46
46
  "devDependencies": {
47
+ "@axe-core/playwright": "^4.13.0",
47
48
  "@eslint/js": "^10.0.1",
48
49
  "@fontsource-variable/bitter": "^5.3.0",
49
50
  "@fontsource-variable/dancing-script": "^5.3.0",
@@ -109,6 +110,7 @@
109
110
  "check:locales:baseline": "node scripts/check-locales.mjs --write-baseline",
110
111
  "validate:iiif": "node scripts/validate-iiif.mjs",
111
112
  "convert:iiif": "node --experimental-strip-types scripts/convert-to-iiif.mjs",
113
+ "convert:slideshow": "node --experimental-strip-types scripts/convert-from-slideshow.mjs",
112
114
  "lint": "eslint . && stylelint 'src/scss/**/*.scss'",
113
115
  "format": "prettier --write .",
114
116
  "format:check": "prettier --check ."