@projektemacher/storymapjs 0.10.7 → 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 (587) hide show
  1. package/CHANGELOG +431 -19
  2. package/README.md +168 -17
  3. package/dist/assets/demo-bWnOyfUw.js +1 -0
  4. package/dist/assets/harness-C3JUv5Ii.js +1 -0
  5. package/dist/assets/harness-multi-XZNex3tb.js +1 -0
  6. package/dist/assets/harness-support-CjfZIVeb.js +1 -0
  7. package/dist/assets/index-wHPqGrBS.js +1 -0
  8. package/dist/assets/main-DQ32hWBM.js +17 -0
  9. package/dist/context.json +23 -9
  10. package/dist/css/fonts/files/amatic-sc-cyrillic-400-normal.woff2 +0 -0
  11. package/dist/css/fonts/files/amatic-sc-cyrillic-700-normal.woff2 +0 -0
  12. package/dist/css/fonts/files/amatic-sc-hebrew-400-normal.woff2 +0 -0
  13. package/dist/css/fonts/files/amatic-sc-hebrew-700-normal.woff2 +0 -0
  14. package/dist/css/fonts/files/amatic-sc-vietnamese-400-normal.woff2 +0 -0
  15. package/dist/css/fonts/files/amatic-sc-vietnamese-700-normal.woff2 +0 -0
  16. package/dist/css/fonts/files/bitter-cyrillic-100-italic.woff2 +0 -0
  17. package/dist/css/fonts/files/bitter-cyrillic-100-normal.woff2 +0 -0
  18. package/dist/css/fonts/files/bitter-cyrillic-200-italic.woff2 +0 -0
  19. package/dist/css/fonts/files/bitter-cyrillic-200-normal.woff2 +0 -0
  20. package/dist/css/fonts/files/bitter-cyrillic-300-italic.woff2 +0 -0
  21. package/dist/css/fonts/files/bitter-cyrillic-300-normal.woff2 +0 -0
  22. package/dist/css/fonts/files/bitter-cyrillic-400-italic.woff2 +0 -0
  23. package/dist/css/fonts/files/bitter-cyrillic-400-normal.woff2 +0 -0
  24. package/dist/css/fonts/files/bitter-cyrillic-500-italic.woff2 +0 -0
  25. package/dist/css/fonts/files/bitter-cyrillic-500-normal.woff2 +0 -0
  26. package/dist/css/fonts/files/bitter-cyrillic-600-italic.woff2 +0 -0
  27. package/dist/css/fonts/files/bitter-cyrillic-600-normal.woff2 +0 -0
  28. package/dist/css/fonts/files/bitter-cyrillic-700-italic.woff2 +0 -0
  29. package/dist/css/fonts/files/bitter-cyrillic-700-normal.woff2 +0 -0
  30. package/dist/css/fonts/files/bitter-cyrillic-800-italic.woff2 +0 -0
  31. package/dist/css/fonts/files/bitter-cyrillic-800-normal.woff2 +0 -0
  32. package/dist/css/fonts/files/bitter-cyrillic-900-italic.woff2 +0 -0
  33. package/dist/css/fonts/files/bitter-cyrillic-900-normal.woff2 +0 -0
  34. package/dist/css/fonts/files/bitter-cyrillic-ext-100-italic.woff2 +0 -0
  35. package/dist/css/fonts/files/bitter-cyrillic-ext-100-normal.woff2 +0 -0
  36. package/dist/css/fonts/files/bitter-cyrillic-ext-200-italic.woff2 +0 -0
  37. package/dist/css/fonts/files/bitter-cyrillic-ext-200-normal.woff2 +0 -0
  38. package/dist/css/fonts/files/bitter-cyrillic-ext-300-italic.woff2 +0 -0
  39. package/dist/css/fonts/files/bitter-cyrillic-ext-300-normal.woff2 +0 -0
  40. package/dist/css/fonts/files/bitter-cyrillic-ext-400-italic.woff2 +0 -0
  41. package/dist/css/fonts/files/bitter-cyrillic-ext-400-normal.woff2 +0 -0
  42. package/dist/css/fonts/files/bitter-cyrillic-ext-500-italic.woff2 +0 -0
  43. package/dist/css/fonts/files/bitter-cyrillic-ext-500-normal.woff2 +0 -0
  44. package/dist/css/fonts/files/bitter-cyrillic-ext-600-italic.woff2 +0 -0
  45. package/dist/css/fonts/files/bitter-cyrillic-ext-600-normal.woff2 +0 -0
  46. package/dist/css/fonts/files/bitter-cyrillic-ext-700-italic.woff2 +0 -0
  47. package/dist/css/fonts/files/bitter-cyrillic-ext-700-normal.woff2 +0 -0
  48. package/dist/css/fonts/files/bitter-cyrillic-ext-800-italic.woff2 +0 -0
  49. package/dist/css/fonts/files/bitter-cyrillic-ext-800-normal.woff2 +0 -0
  50. package/dist/css/fonts/files/bitter-cyrillic-ext-900-italic.woff2 +0 -0
  51. package/dist/css/fonts/files/bitter-cyrillic-ext-900-normal.woff2 +0 -0
  52. package/dist/css/fonts/files/bitter-cyrillic-ext-wght-italic.woff2 +0 -0
  53. package/dist/css/fonts/files/bitter-cyrillic-ext-wght-normal.woff2 +0 -0
  54. package/dist/css/fonts/files/bitter-cyrillic-wght-italic.woff2 +0 -0
  55. package/dist/css/fonts/files/bitter-cyrillic-wght-normal.woff2 +0 -0
  56. package/dist/css/fonts/files/bitter-vietnamese-100-italic.woff2 +0 -0
  57. package/dist/css/fonts/files/bitter-vietnamese-100-normal.woff2 +0 -0
  58. package/dist/css/fonts/files/bitter-vietnamese-200-italic.woff2 +0 -0
  59. package/dist/css/fonts/files/bitter-vietnamese-200-normal.woff2 +0 -0
  60. package/dist/css/fonts/files/bitter-vietnamese-300-italic.woff2 +0 -0
  61. package/dist/css/fonts/files/bitter-vietnamese-300-normal.woff2 +0 -0
  62. package/dist/css/fonts/files/bitter-vietnamese-400-italic.woff2 +0 -0
  63. package/dist/css/fonts/files/bitter-vietnamese-400-normal.woff2 +0 -0
  64. package/dist/css/fonts/files/bitter-vietnamese-500-italic.woff2 +0 -0
  65. package/dist/css/fonts/files/bitter-vietnamese-500-normal.woff2 +0 -0
  66. package/dist/css/fonts/files/bitter-vietnamese-600-italic.woff2 +0 -0
  67. package/dist/css/fonts/files/bitter-vietnamese-600-normal.woff2 +0 -0
  68. package/dist/css/fonts/files/bitter-vietnamese-700-italic.woff2 +0 -0
  69. package/dist/css/fonts/files/bitter-vietnamese-700-normal.woff2 +0 -0
  70. package/dist/css/fonts/files/bitter-vietnamese-800-italic.woff2 +0 -0
  71. package/dist/css/fonts/files/bitter-vietnamese-800-normal.woff2 +0 -0
  72. package/dist/css/fonts/files/bitter-vietnamese-900-italic.woff2 +0 -0
  73. package/dist/css/fonts/files/bitter-vietnamese-900-normal.woff2 +0 -0
  74. package/dist/css/fonts/files/bitter-vietnamese-wght-italic.woff2 +0 -0
  75. package/dist/css/fonts/files/bitter-vietnamese-wght-normal.woff2 +0 -0
  76. package/dist/css/fonts/files/cairo-arabic-200-normal.woff2 +0 -0
  77. package/dist/css/fonts/files/cairo-arabic-300-normal.woff2 +0 -0
  78. package/dist/css/fonts/files/cairo-arabic-400-normal.woff2 +0 -0
  79. package/dist/css/fonts/files/cairo-arabic-500-normal.woff2 +0 -0
  80. package/dist/css/fonts/files/cairo-arabic-600-normal.woff2 +0 -0
  81. package/dist/css/fonts/files/cairo-arabic-700-normal.woff2 +0 -0
  82. package/dist/css/fonts/files/cairo-arabic-800-normal.woff2 +0 -0
  83. package/dist/css/fonts/files/cairo-arabic-900-normal.woff2 +0 -0
  84. package/dist/css/fonts/files/cairo-latin-200-normal.woff2 +0 -0
  85. package/dist/css/fonts/files/cairo-latin-300-normal.woff2 +0 -0
  86. package/dist/css/fonts/files/cairo-latin-400-normal.woff2 +0 -0
  87. package/dist/css/fonts/files/cairo-latin-500-normal.woff2 +0 -0
  88. package/dist/css/fonts/files/cairo-latin-600-normal.woff2 +0 -0
  89. package/dist/css/fonts/files/cairo-latin-700-normal.woff2 +0 -0
  90. package/dist/css/fonts/files/cairo-latin-800-normal.woff2 +0 -0
  91. package/dist/css/fonts/files/cairo-latin-900-normal.woff2 +0 -0
  92. package/dist/css/fonts/files/cairo-latin-ext-200-normal.woff2 +0 -0
  93. package/dist/css/fonts/files/cairo-latin-ext-300-normal.woff2 +0 -0
  94. package/dist/css/fonts/files/cairo-latin-ext-400-normal.woff2 +0 -0
  95. package/dist/css/fonts/files/cairo-latin-ext-500-normal.woff2 +0 -0
  96. package/dist/css/fonts/files/cairo-latin-ext-600-normal.woff2 +0 -0
  97. package/dist/css/fonts/files/cairo-latin-ext-700-normal.woff2 +0 -0
  98. package/dist/css/fonts/files/cairo-latin-ext-800-normal.woff2 +0 -0
  99. package/dist/css/fonts/files/cairo-latin-ext-900-normal.woff2 +0 -0
  100. package/dist/css/fonts/files/dancing-script-vietnamese-wght-normal.woff2 +0 -0
  101. package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-italic.woff2 +0 -0
  102. package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-normal.woff2 +0 -0
  103. package/dist/css/fonts/files/eb-garamond-cyrillic-wght-italic.woff2 +0 -0
  104. package/dist/css/fonts/files/eb-garamond-cyrillic-wght-normal.woff2 +0 -0
  105. package/dist/css/fonts/files/eb-garamond-greek-ext-wght-italic.woff2 +0 -0
  106. package/dist/css/fonts/files/eb-garamond-greek-ext-wght-normal.woff2 +0 -0
  107. package/dist/css/fonts/files/eb-garamond-greek-wght-italic.woff2 +0 -0
  108. package/dist/css/fonts/files/eb-garamond-greek-wght-normal.woff2 +0 -0
  109. package/dist/css/fonts/files/eb-garamond-vietnamese-wght-italic.woff2 +0 -0
  110. package/dist/css/fonts/files/eb-garamond-vietnamese-wght-normal.woff2 +0 -0
  111. package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-italic.woff2 +0 -0
  112. package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-normal.woff2 +0 -0
  113. package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-italic.woff2 +0 -0
  114. package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-normal.woff2 +0 -0
  115. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-italic.woff2 +0 -0
  116. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-normal.woff2 +0 -0
  117. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-italic.woff2 +0 -0
  118. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-normal.woff2 +0 -0
  119. package/dist/css/fonts/files/gentium-book-plus-greek-400-italic.woff2 +0 -0
  120. package/dist/css/fonts/files/gentium-book-plus-greek-400-normal.woff2 +0 -0
  121. package/dist/css/fonts/files/gentium-book-plus-greek-700-italic.woff2 +0 -0
  122. package/dist/css/fonts/files/gentium-book-plus-greek-700-normal.woff2 +0 -0
  123. package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-italic.woff2 +0 -0
  124. package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-normal.woff2 +0 -0
  125. package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-italic.woff2 +0 -0
  126. package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-normal.woff2 +0 -0
  127. package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-italic.woff2 +0 -0
  128. package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-normal.woff2 +0 -0
  129. package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-italic.woff2 +0 -0
  130. package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-normal.woff2 +0 -0
  131. package/dist/css/fonts/files/old-standard-tt-cyrillic-400-italic.woff2 +0 -0
  132. package/dist/css/fonts/files/old-standard-tt-cyrillic-400-normal.woff2 +0 -0
  133. package/dist/css/fonts/files/old-standard-tt-cyrillic-700-normal.woff2 +0 -0
  134. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-italic.woff2 +0 -0
  135. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-normal.woff2 +0 -0
  136. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-700-normal.woff2 +0 -0
  137. package/dist/css/fonts/files/old-standard-tt-vietnamese-400-italic.woff2 +0 -0
  138. package/dist/css/fonts/files/old-standard-tt-vietnamese-400-normal.woff2 +0 -0
  139. package/dist/css/fonts/files/old-standard-tt-vietnamese-700-normal.woff2 +0 -0
  140. package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-italic.woff2 +0 -0
  141. package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-normal.woff2 +0 -0
  142. package/dist/css/fonts/files/open-sans-cyrillic-wght-italic.woff2 +0 -0
  143. package/dist/css/fonts/files/open-sans-cyrillic-wght-normal.woff2 +0 -0
  144. package/dist/css/fonts/files/open-sans-greek-ext-wght-italic.woff2 +0 -0
  145. package/dist/css/fonts/files/open-sans-greek-ext-wght-normal.woff2 +0 -0
  146. package/dist/css/fonts/files/open-sans-greek-wght-italic.woff2 +0 -0
  147. package/dist/css/fonts/files/open-sans-greek-wght-normal.woff2 +0 -0
  148. package/dist/css/fonts/files/open-sans-hebrew-wght-italic.woff2 +0 -0
  149. package/dist/css/fonts/files/open-sans-hebrew-wght-normal.woff2 +0 -0
  150. package/dist/css/fonts/files/open-sans-vietnamese-wght-italic.woff2 +0 -0
  151. package/dist/css/fonts/files/open-sans-vietnamese-wght-normal.woff2 +0 -0
  152. package/dist/css/fonts/files/playfair-display-cyrillic-wght-italic.woff2 +0 -0
  153. package/dist/css/fonts/files/playfair-display-cyrillic-wght-normal.woff2 +0 -0
  154. package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-italic.woff2 +0 -0
  155. package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-normal.woff2 +0 -0
  156. package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-italic.woff2 +0 -0
  157. package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-normal.woff2 +0 -0
  158. package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-italic.woff2 +0 -0
  159. package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-normal.woff2 +0 -0
  160. package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-italic.woff2 +0 -0
  161. package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-normal.woff2 +0 -0
  162. package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-italic.woff2 +0 -0
  163. package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-normal.woff2 +0 -0
  164. package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-italic.woff2 +0 -0
  165. package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-normal.woff2 +0 -0
  166. package/dist/css/fonts/files/playfair-display-vietnamese-wght-italic.woff2 +0 -0
  167. package/dist/css/fonts/files/playfair-display-vietnamese-wght-normal.woff2 +0 -0
  168. package/dist/css/fonts/files/pt-sans-cyrillic-400-italic.woff2 +0 -0
  169. package/dist/css/fonts/files/pt-sans-cyrillic-400-normal.woff2 +0 -0
  170. package/dist/css/fonts/files/pt-sans-cyrillic-700-italic.woff2 +0 -0
  171. package/dist/css/fonts/files/pt-sans-cyrillic-700-normal.woff2 +0 -0
  172. package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-italic.woff2 +0 -0
  173. package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-normal.woff2 +0 -0
  174. package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-italic.woff2 +0 -0
  175. package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-normal.woff2 +0 -0
  176. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-400-normal.woff2 +0 -0
  177. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-700-normal.woff2 +0 -0
  178. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-400-normal.woff2 +0 -0
  179. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-700-normal.woff2 +0 -0
  180. package/dist/css/fonts/files/pt-serif-cyrillic-400-italic.woff2 +0 -0
  181. package/dist/css/fonts/files/pt-serif-cyrillic-400-normal.woff2 +0 -0
  182. package/dist/css/fonts/files/pt-serif-cyrillic-700-italic.woff2 +0 -0
  183. package/dist/css/fonts/files/pt-serif-cyrillic-700-normal.woff2 +0 -0
  184. package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-italic.woff2 +0 -0
  185. package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-normal.woff2 +0 -0
  186. package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-italic.woff2 +0 -0
  187. package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-normal.woff2 +0 -0
  188. package/dist/css/fonts/files/raleway-cyrillic-ext-wght-italic.woff2 +0 -0
  189. package/dist/css/fonts/files/raleway-cyrillic-ext-wght-normal.woff2 +0 -0
  190. package/dist/css/fonts/files/raleway-cyrillic-wght-italic.woff2 +0 -0
  191. package/dist/css/fonts/files/raleway-cyrillic-wght-normal.woff2 +0 -0
  192. package/dist/css/fonts/files/raleway-vietnamese-wght-italic.woff2 +0 -0
  193. package/dist/css/fonts/files/raleway-vietnamese-wght-normal.woff2 +0 -0
  194. package/dist/css/fonts/files/roboto-slab-cyrillic-ext-wght-normal.woff2 +0 -0
  195. package/dist/css/fonts/files/roboto-slab-cyrillic-wght-normal.woff2 +0 -0
  196. package/dist/css/fonts/files/roboto-slab-greek-ext-wght-normal.woff2 +0 -0
  197. package/dist/css/fonts/files/roboto-slab-greek-wght-normal.woff2 +0 -0
  198. package/dist/css/fonts/files/roboto-slab-vietnamese-wght-normal.woff2 +0 -0
  199. package/dist/css/fonts/files/ubuntu-cyrillic-300-italic.woff2 +0 -0
  200. package/dist/css/fonts/files/ubuntu-cyrillic-300-normal.woff2 +0 -0
  201. package/dist/css/fonts/files/ubuntu-cyrillic-400-italic.woff2 +0 -0
  202. package/dist/css/fonts/files/ubuntu-cyrillic-400-normal.woff2 +0 -0
  203. package/dist/css/fonts/files/ubuntu-cyrillic-500-italic.woff2 +0 -0
  204. package/dist/css/fonts/files/ubuntu-cyrillic-500-normal.woff2 +0 -0
  205. package/dist/css/fonts/files/ubuntu-cyrillic-700-italic.woff2 +0 -0
  206. package/dist/css/fonts/files/ubuntu-cyrillic-700-normal.woff2 +0 -0
  207. package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-italic.woff2 +0 -0
  208. package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-normal.woff2 +0 -0
  209. package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-italic.woff2 +0 -0
  210. package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-normal.woff2 +0 -0
  211. package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-italic.woff2 +0 -0
  212. package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-normal.woff2 +0 -0
  213. package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-italic.woff2 +0 -0
  214. package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-normal.woff2 +0 -0
  215. package/dist/css/fonts/files/ubuntu-greek-300-italic.woff2 +0 -0
  216. package/dist/css/fonts/files/ubuntu-greek-300-normal.woff2 +0 -0
  217. package/dist/css/fonts/files/ubuntu-greek-400-italic.woff2 +0 -0
  218. package/dist/css/fonts/files/ubuntu-greek-400-normal.woff2 +0 -0
  219. package/dist/css/fonts/files/ubuntu-greek-500-italic.woff2 +0 -0
  220. package/dist/css/fonts/files/ubuntu-greek-500-normal.woff2 +0 -0
  221. package/dist/css/fonts/files/ubuntu-greek-700-italic.woff2 +0 -0
  222. package/dist/css/fonts/files/ubuntu-greek-700-normal.woff2 +0 -0
  223. package/dist/css/fonts/files/ubuntu-greek-ext-300-italic.woff2 +0 -0
  224. package/dist/css/fonts/files/ubuntu-greek-ext-300-normal.woff2 +0 -0
  225. package/dist/css/fonts/files/ubuntu-greek-ext-400-italic.woff2 +0 -0
  226. package/dist/css/fonts/files/ubuntu-greek-ext-400-normal.woff2 +0 -0
  227. package/dist/css/fonts/files/ubuntu-greek-ext-500-italic.woff2 +0 -0
  228. package/dist/css/fonts/files/ubuntu-greek-ext-500-normal.woff2 +0 -0
  229. package/dist/css/fonts/files/ubuntu-greek-ext-700-italic.woff2 +0 -0
  230. package/dist/css/fonts/files/ubuntu-greek-ext-700-normal.woff2 +0 -0
  231. package/dist/css/fonts/files/unica-one-vietnamese-400-normal.woff2 +0 -0
  232. package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-italic.woff2 +0 -0
  233. package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-normal.woff2 +0 -0
  234. package/dist/css/fonts/files/vollkorn-cyrillic-wght-italic.woff2 +0 -0
  235. package/dist/css/fonts/files/vollkorn-cyrillic-wght-normal.woff2 +0 -0
  236. package/dist/css/fonts/files/vollkorn-greek-wght-italic.woff2 +0 -0
  237. package/dist/css/fonts/files/vollkorn-greek-wght-normal.woff2 +0 -0
  238. package/dist/css/fonts/files/vollkorn-vietnamese-wght-italic.woff2 +0 -0
  239. package/dist/css/fonts/files/vollkorn-vietnamese-wght-normal.woff2 +0 -0
  240. package/dist/css/fonts/font.abril-droidsans.css +3 -0
  241. package/dist/css/fonts/font.amatic-andika.css +57 -0
  242. package/dist/css/fonts/font.bitter-raleway.css +111 -0
  243. package/dist/css/fonts/font.cairo.css +312 -0
  244. package/dist/css/fonts/font.clicker-garamond.css +93 -0
  245. package/dist/css/fonts/font.dancing-ledger.css +12 -0
  246. package/dist/css/fonts/font.default.css +183 -0
  247. package/dist/css/fonts/font.fjalla-average.css +3 -0
  248. package/dist/css/fonts/font.georgia-helvetica.css +3 -0
  249. package/dist/css/fonts/font.knightlab.css +642 -0
  250. package/dist/css/fonts/font.lustria-lato.css +3 -0
  251. package/dist/css/fonts/font.medula-lato.css +3 -0
  252. package/dist/css/fonts/font.oldstandard.css +84 -0
  253. package/dist/css/fonts/font.opensans-gentiumbook.css +183 -0
  254. package/dist/css/fonts/font.playfair-faunaone.css +39 -0
  255. package/dist/css/fonts/font.playfair.css +147 -0
  256. package/dist/css/fonts/font.pt.css +183 -0
  257. package/dist/css/fonts/font.roboto-megrim.css +3 -0
  258. package/dist/css/fonts/font.rufina-sintony.css +3 -0
  259. package/dist/css/fonts/font.ubuntu.css +291 -0
  260. package/dist/css/fonts/font.unicaone-vollkorn.css +84 -0
  261. package/dist/css/storymap.css +1 -1
  262. package/dist/demo.html +3 -2
  263. package/dist/docs/api/.nojekyll +1 -0
  264. package/dist/docs/api/assets/custom.css +47 -0
  265. package/dist/docs/api/assets/hierarchy.js +1 -0
  266. package/dist/docs/api/assets/highlight.css +57 -0
  267. package/dist/docs/api/assets/icons.js +18 -0
  268. package/dist/docs/api/assets/icons.svg +1 -0
  269. package/dist/docs/api/assets/main.js +60 -0
  270. package/dist/docs/api/assets/navigation.js +1 -0
  271. package/dist/docs/api/assets/search.js +1 -0
  272. package/dist/docs/api/assets/style.css +1648 -0
  273. package/dist/docs/api/classes/StoryMap.html +2112 -0
  274. package/dist/docs/api/functions/MediaType.html +51 -0
  275. package/dist/docs/api/functions/isPresentation3Collection.html +47 -0
  276. package/dist/docs/api/functions/isPresentation3Manifest.html +53 -0
  277. package/dist/docs/api/functions/isSlideshowCollection.html +51 -0
  278. package/dist/docs/api/functions/loadCSS.html +63 -0
  279. package/dist/docs/api/functions/manifestToStorymapData.html +49 -0
  280. package/dist/docs/api/functions/setLanguage.html +54 -0
  281. package/dist/docs/api/functions/slideshowToStorymapData.html +51 -0
  282. package/dist/docs/api/functions/slideshowVersion.html +48 -0
  283. package/dist/docs/api/functions/storymapToManifest.html +57 -0
  284. package/dist/docs/api/functions/validateStorymap.html +53 -0
  285. package/dist/docs/api/functions/validateStorymapAndReport.html +54 -0
  286. package/dist/docs/api/hierarchy.html +28 -0
  287. package/dist/docs/api/index.html +300 -0
  288. package/dist/docs/api/interfaces/AnimationHandle.html +60 -0
  289. package/dist/docs/api/interfaces/ImagereadyPayload.html +71 -0
  290. package/dist/docs/api/interfaces/LanguageEntry.html +102 -0
  291. package/dist/docs/api/interfaces/LatLngLiteral.html +73 -0
  292. package/dist/docs/api/interfaces/LoadOptions.html +59 -0
  293. package/dist/docs/api/interfaces/MapEvents.html +116 -0
  294. package/dist/docs/api/interfaces/MapMarkerEvents.html +66 -0
  295. package/dist/docs/api/interfaces/MarkerEventPayload.html +57 -0
  296. package/dist/docs/api/interfaces/MediaEvents.html +78 -0
  297. package/dist/docs/api/interfaces/MenuBarEvents.html +114 -0
  298. package/dist/docs/api/interfaces/MessageEvents.html +72 -0
  299. package/dist/docs/api/interfaces/OlLayer.html +1400 -0
  300. package/dist/docs/api/interfaces/OlMap.html +1656 -0
  301. package/dist/docs/api/interfaces/OlProjection.html +332 -0
  302. package/dist/docs/api/interfaces/OlSource.html +784 -0
  303. package/dist/docs/api/interfaces/OlTileLayer.html +1497 -0
  304. package/dist/docs/api/interfaces/OlVectorLayer.html +1559 -0
  305. package/dist/docs/api/interfaces/OlView.html +1958 -0
  306. package/dist/docs/api/interfaces/SlideBackgroundState.html +66 -0
  307. package/dist/docs/api/interfaces/SlideEvents.html +78 -0
  308. package/dist/docs/api/interfaces/SlideNavEvents.html +72 -0
  309. package/dist/docs/api/interfaces/SlideshowPlayerSettings.html +182 -0
  310. package/dist/docs/api/interfaces/SlideshowToStorymapResult.html +60 -0
  311. package/dist/docs/api/interfaces/SlideshowTranslatorOptions.html +65 -0
  312. package/dist/docs/api/interfaces/SlideshowWarning.html +72 -0
  313. package/dist/docs/api/interfaces/StoryMapEvents.html +146 -0
  314. package/dist/docs/api/interfaces/StoryMapMarker.html +763 -0
  315. package/dist/docs/api/interfaces/StorySliderEvents.html +102 -0
  316. package/dist/docs/api/interfaces/StorymapBasemap.html +69 -0
  317. package/dist/docs/api/interfaces/StorymapData.html +77 -0
  318. package/dist/docs/api/interfaces/StorymapDataWrapper.html +60 -0
  319. package/dist/docs/api/interfaces/StorymapDocument.html +68 -0
  320. package/dist/docs/api/interfaces/StorymapError.html +63 -0
  321. package/dist/docs/api/interfaces/StorymapGeoreference.html +93 -0
  322. package/dist/docs/api/interfaces/StorymapGeoreferenceBody.html +74 -0
  323. package/dist/docs/api/interfaces/StorymapGroundControlPoint.html +69 -0
  324. package/dist/docs/api/interfaces/StorymapLanguageMap.html +57 -0
  325. package/dist/docs/api/interfaces/StorymapManifest.html +118 -0
  326. package/dist/docs/api/interfaces/StorymapManifestAnnotation.html +137 -0
  327. package/dist/docs/api/interfaces/StorymapManifestBackground.html +81 -0
  328. package/dist/docs/api/interfaces/StorymapManifestCanvas.html +188 -0
  329. package/dist/docs/api/interfaces/StorymapManifestContentResource.html +97 -0
  330. package/dist/docs/api/interfaces/StorymapManifestFeatureCollection.html +82 -0
  331. package/dist/docs/api/interfaces/StorymapManifestGeoreferencing.html +87 -0
  332. package/dist/docs/api/interfaces/StorymapManifestImageService.html +69 -0
  333. package/dist/docs/api/interfaces/StorymapManifestRange.html +75 -0
  334. package/dist/docs/api/interfaces/StorymapManifestService.html +77 -0
  335. package/dist/docs/api/interfaces/StorymapManifestSpecificResource.html +69 -0
  336. package/dist/docs/api/interfaces/StorymapManifestStatement.html +63 -0
  337. package/dist/docs/api/interfaces/StorymapMapOptions.html +92 -0
  338. package/dist/docs/api/interfaces/StorymapOptions.html +734 -0
  339. package/dist/docs/api/interfaces/StorymapOverlayLayer.html +157 -0
  340. package/dist/docs/api/interfaces/StorymapSlide.html +186 -0
  341. package/dist/docs/api/interfaces/StorymapSlideBackground.html +72 -0
  342. package/dist/docs/api/interfaces/StorymapSlideLocation.html +161 -0
  343. package/dist/docs/api/interfaces/StorymapSlideMarker.html +103 -0
  344. package/dist/docs/api/interfaces/StorymapSlideMedia.html +149 -0
  345. package/dist/docs/api/interfaces/StorymapSlideNarration.html +117 -0
  346. package/dist/docs/api/interfaces/StorymapSlideText.html +72 -0
  347. package/dist/docs/api/interfaces/StorymapTilejson.html +105 -0
  348. package/dist/docs/api/interfaces/SwipableEvents.html +102 -0
  349. package/dist/docs/api/interfaces/TextEvents.html +66 -0
  350. package/dist/docs/api/media/es.json +31 -0
  351. package/dist/docs/api/media/events.md +66 -0
  352. package/dist/docs/api/media/migration-from-knightlab.md +399 -0
  353. package/dist/docs/api/media/slideshow.md +109 -0
  354. package/dist/docs/api/media/storymap-as-iiif-manifest.md +1007 -0
  355. package/dist/docs/api/modules.html +50 -0
  356. package/dist/docs/api/types/ContentState.html +70 -0
  357. package/dist/docs/api/types/FiredEvent.html +43 -0
  358. package/dist/docs/api/types/ImagereadyKind.html +34 -0
  359. package/dist/docs/api/types/MediaTypeMatch.html +78 -0
  360. package/dist/docs/api/types/SwipeDirection.html +36 -0
  361. package/dist/docs/api/types/TileSourceFactory.html +53 -0
  362. package/dist/docs/authoring.html +306 -0
  363. package/dist/docs/events.html +263 -0
  364. package/dist/docs/iiif.html +738 -69
  365. package/dist/docs/migration.html +360 -11
  366. package/dist/docs/readme.html +149 -17
  367. package/dist/embed/index.html +8 -1
  368. package/dist/examples/font-css-false.json +33 -0
  369. package/dist/examples/issue-242-nonlatin.json +55 -0
  370. package/dist/examples/issue-305-start-at-slide-data.json +96 -0
  371. package/dist/examples/issue-358-iframe.json +57 -0
  372. package/dist/examples/issue-iiif-geo.json +32 -0
  373. package/dist/examples/issue-image-alt.json +23 -0
  374. package/dist/examples/issue-image-region.json +42 -0
  375. package/dist/examples/issue-image-srcset.json +24 -0
  376. package/dist/examples/layers-control.json +60 -0
  377. package/dist/examples/map-area-overlays.json +68 -0
  378. package/dist/examples/map-template-provider.json +36 -0
  379. package/dist/examples/multi-media.json +71 -0
  380. package/dist/examples/no-map.json +44 -0
  381. package/dist/examples-iiif/annotated-image.json +204 -0
  382. package/dist/examples-iiif/bob-boilen.json +11 -5
  383. package/dist/examples-iiif/courbet.json +9 -6
  384. package/dist/examples-iiif/empty.json +8 -4
  385. package/dist/examples-iiif/flickr-drewvigal.json +248 -24
  386. package/dist/examples-iiif/flickr-zach.wise.json +8 -4
  387. package/dist/examples-iiif/font-css-false.json +114 -0
  388. package/dist/examples-iiif/georeferenced-layer-unsupported.json +153 -0
  389. package/dist/examples-iiif/georeferenced-layer.json +318 -0
  390. package/dist/examples-iiif/iiif-wellcome.json +9 -6
  391. package/dist/examples-iiif/instagram-chenpamela.json +381 -36
  392. package/dist/examples-iiif/instagram_brentfoster.json +429 -40
  393. package/dist/examples-iiif/instagram_couch.json +261 -26
  394. package/dist/examples-iiif/instagram_joegermuska.json +441 -41
  395. package/dist/examples-iiif/instagram_matteich.json +261 -26
  396. package/dist/examples-iiif/instagram_mirandamulligan.json +261 -26
  397. package/dist/examples-iiif/instagram_raymondmccrea.json +261 -26
  398. package/dist/examples-iiif/instagram_test.json +261 -26
  399. package/dist/examples-iiif/issue-134-no-lines.json +9 -5
  400. package/dist/examples-iiif/issue-177-color-vars.json +9 -5
  401. package/dist/examples-iiif/issue-211-rtl.json +9 -5
  402. package/dist/examples-iiif/issue-242-nonlatin.json +239 -0
  403. package/dist/examples-iiif/issue-272-facebook.json +9 -5
  404. package/dist/examples-iiif/issue-305-start-at-slide-data.json +305 -0
  405. package/dist/examples-iiif/issue-305-start-at-slide.json +9 -5
  406. package/dist/examples-iiif/issue-341-distance.json +9 -5
  407. package/dist/examples-iiif/issue-358-iframe.json +190 -0
  408. package/dist/examples-iiif/issue-360-juxtapose.json +22 -7
  409. package/dist/examples-iiif/issue-368-null-fields.json +9 -5
  410. package/dist/examples-iiif/issue-375-code-lists.json +9 -5
  411. package/dist/examples-iiif/issue-381-dateline.json +9 -5
  412. package/dist/examples-iiif/issue-405-custom-icon.json +203 -0
  413. package/dist/examples-iiif/issue-425-many-slides.json +9 -5
  414. package/dist/examples-iiif/issue-428-background.json +20 -8
  415. package/dist/examples-iiif/issue-435-googlemaps.json +9 -5
  416. package/dist/examples-iiif/issue-437-documentcloud.json +22 -7
  417. package/dist/examples-iiif/issue-451-webp.json +9 -5
  418. package/dist/examples-iiif/issue-455-audio.json +9 -5
  419. package/dist/examples-iiif/issue-480-shorts.json +9 -5
  420. package/dist/examples-iiif/issue-506-marker-sync.json +9 -5
  421. package/dist/examples-iiif/issue-iiif-geo.json +200 -0
  422. package/dist/examples-iiif/issue-image-alt.json +90 -0
  423. package/dist/examples-iiif/issue-image-region.json +203 -0
  424. package/dist/examples-iiif/issue-image-srcset.json +87 -0
  425. package/dist/examples-iiif/jansteen.json +9 -6
  426. package/dist/examples-iiif/katrina.json +197 -41
  427. package/dist/examples-iiif/layers-control.json +226 -0
  428. package/dist/examples-iiif/map-area-overlays.json +289 -0
  429. package/dist/examples-iiif/map-template-provider.json +133 -0
  430. package/dist/examples-iiif/marktwain.json +255 -58
  431. package/dist/examples-iiif/multi-media.json +237 -0
  432. package/dist/examples-iiif/no-map.json +148 -0
  433. package/dist/examples-iiif/population.json +440 -76
  434. package/dist/examples-iiif/president.json +456 -83
  435. package/dist/examples-iiif/scroll-hint.json +190 -0
  436. package/dist/examples-iiif/seurat.json +113 -22
  437. package/dist/examples-iiif/zoomify-clamp.json +153 -0
  438. package/dist/examples-slideshow/single.json +79 -0
  439. package/dist/examples-slideshow/static/pixel.png +0 -0
  440. package/dist/examples-slideshow/static.json +44 -0
  441. package/dist/harness-multi.html +17 -0
  442. package/dist/harness.html +4 -2
  443. package/dist/index.html +19 -12
  444. package/dist/js/storymap.d.ts +2669 -307
  445. package/dist/js/storymap.js +10820 -6196
  446. package/dist/js/storymap.js.map +1 -1
  447. package/dist/navplace-properties.json +54 -0
  448. package/dist/site.css +54 -36
  449. package/docs/migration-from-knightlab.md +279 -19
  450. package/docs/storymap-as-iiif-manifest.md +633 -136
  451. package/package.json +12 -7
  452. package/schema/storymap.schema.json +733 -80
  453. package/src/animation/easings.ts +8 -1
  454. package/src/animation/tween.ts +186 -0
  455. package/src/core/Browser.ts +6 -5
  456. package/src/core/Load.ts +54 -2
  457. package/src/core/Util.ts +257 -193
  458. package/src/core/mixins.ts +66 -35
  459. package/src/core/viewers.ts +94 -0
  460. package/src/dom/DomEvent.ts +27 -8
  461. package/src/globals.d.ts +8 -0
  462. package/src/language/Language.ts +206 -25
  463. package/src/language/locale/.expected-gaps.json +346 -0
  464. package/src/language/locale/be.json +15 -2
  465. package/src/language/locale/bg.json +15 -2
  466. package/src/language/locale/cs.json +15 -2
  467. package/src/language/locale/de.json +23 -2
  468. package/src/language/locale/el.json +15 -2
  469. package/src/language/locale/en.json +17 -3
  470. package/src/language/locale/es.json +15 -2
  471. package/src/language/locale/et.json +5 -1
  472. package/src/language/locale/fr.json +15 -2
  473. package/src/language/locale/he.json +16 -3
  474. package/src/language/locale/hu.json +15 -2
  475. package/src/language/locale/is.json +5 -1
  476. package/src/language/locale/it.json +15 -2
  477. package/src/language/locale/jp.json +15 -2
  478. package/src/language/locale/ko.json +15 -2
  479. package/src/language/locale/nl.json +15 -2
  480. package/src/language/locale/nn.json +5 -1
  481. package/src/language/locale/no.json +15 -2
  482. package/src/language/locale/pl.json +15 -2
  483. package/src/language/locale/pt.json +15 -2
  484. package/src/language/locale/ru.json +15 -2
  485. package/src/language/locale/sk.json +15 -2
  486. package/src/language/locale/sr.json +5 -1
  487. package/src/language/locale/sv.json +15 -2
  488. package/src/language/locale/tr.json +15 -2
  489. package/src/language/locale/uk.json +15 -2
  490. package/src/language/locale/ur.json +5 -1
  491. package/src/language/locale/zh-cn.json +15 -2
  492. package/src/language/locale/zh-tw.json +15 -2
  493. package/src/main.ts +143 -0
  494. package/src/map/Map.ts +227 -112
  495. package/src/map/MapMarker.ts +44 -8
  496. package/src/map/georeference.ts +325 -0
  497. package/src/map/openlayers/Map.OpenLayers.ts +1601 -263
  498. package/src/map/openlayers/MapMarker.OpenLayers.ts +348 -24
  499. package/src/map/openlayers/zoomifyTiles.ts +1 -4
  500. package/src/map/slideView.ts +149 -0
  501. package/src/map/types.ts +2 -0
  502. package/src/media/EmbedUtil.ts +333 -24
  503. package/src/media/Media.ts +270 -59
  504. package/src/media/embedId.ts +110 -0
  505. package/src/media/types/Audio.ts +9 -82
  506. package/src/media/types/Blockquote.ts +2 -3
  507. package/src/media/types/DailyMotion.ts +5 -10
  508. package/src/media/types/DocumentCloud.ts +6 -35
  509. package/src/media/types/Facebook.ts +3 -4
  510. package/src/media/types/Flickr.ts +23 -12
  511. package/src/media/types/GoogleDoc.ts +3 -4
  512. package/src/media/types/HtmlMedia.ts +233 -0
  513. package/src/media/types/IFrame.ts +3 -4
  514. package/src/media/types/Image.ts +87 -9
  515. package/src/media/types/Juxtapose.ts +14 -5
  516. package/src/media/types/SoundCloud.ts +28 -6
  517. package/src/media/types/Text.ts +46 -21
  518. package/src/media/types/Twitter.ts +35 -20
  519. package/src/media/types/Video.ts +9 -79
  520. package/src/media/types/Vimeo.ts +11 -11
  521. package/src/media/types/Website.ts +23 -13
  522. package/src/media/types/Wikipedia.ts +18 -8
  523. package/src/media/types/YouTube.ts +72 -40
  524. package/src/scss/Typography.scss +16 -18
  525. package/src/scss/VCO.StoryMap.scss +208 -12
  526. package/src/scss/Variables.scss +3 -2
  527. package/src/scss/core/Mixins.scss +5 -63
  528. package/src/scss/core/Reset.scss +5 -18
  529. package/src/scss/fonts/font.amatic-andika.scss +3 -0
  530. package/src/scss/fonts/font.bitter-raleway.scss +6 -0
  531. package/src/scss/fonts/font.cairo.scss +79 -0
  532. package/src/scss/fonts/font.clicker-garamond.scss +5 -0
  533. package/src/scss/fonts/font.dancing-ledger.scss +1 -0
  534. package/src/scss/fonts/font.knightlab.scss +14 -0
  535. package/src/scss/fonts/font.oldstandard.scss +6 -0
  536. package/src/scss/fonts/font.opensans-gentiumbook.scss +5 -0
  537. package/src/scss/fonts/font.playfair-faunaone.scss +2 -0
  538. package/src/scss/fonts/font.playfair.scss +4 -0
  539. package/src/scss/fonts/font.pt.scss +6 -0
  540. package/src/scss/fonts/font.ubuntu.scss +4 -0
  541. package/src/scss/fonts/font.unicaone-vollkorn.scss +5 -0
  542. package/src/scss/map/VCO.Map.scss +1 -1
  543. package/src/scss/map/VCO.MapMarker.scss +114 -8
  544. package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +7 -4
  545. package/src/scss/media/VCO.Media.scss +14 -17
  546. package/src/scss/media/types/VCO.Media.Blockquote.scss +1 -1
  547. package/src/scss/media/types/VCO.Media.Text.scss +13 -5
  548. package/src/scss/media/types/VCO.Media.Twitter.scss +4 -4
  549. package/src/scss/media/types/VCO.Media.Wikipedia.scss +3 -19
  550. package/src/scss/site/site.scss +55 -36
  551. package/src/scss/slider/VCO.Slide.scss +61 -13
  552. package/src/scss/slider/VCO.SlideNav.scss +34 -24
  553. package/src/scss/slider/VCO.StorySlider.scss +53 -1
  554. package/src/scss/snapmap/VCO.SnapMap.scss +3 -3
  555. package/src/scss/ui/VCO.Consent.scss +63 -13
  556. package/src/scss/ui/VCO.Layers.scss +119 -0
  557. package/src/scss/ui/VCO.MenuBar.Button.scss +143 -14
  558. package/src/scss/ui/VCO.MenuBar.scss +9 -2
  559. package/src/scss/ui/VCO.Message.scss +16 -5
  560. package/src/site/site.ts +2 -1
  561. package/src/slider/Slide.ts +326 -74
  562. package/src/slider/SlideNav.ts +54 -9
  563. package/src/slider/StorySlider.ts +352 -60
  564. package/src/storymap/Consent.ts +429 -82
  565. package/src/storymap/StoryMap.ts +2163 -340
  566. package/src/storymap/content-state.ts +180 -0
  567. package/src/storymap/font-css.ts +72 -0
  568. package/src/storymap/from-slideshow.ts +785 -0
  569. package/src/storymap/iiif-shared.ts +228 -0
  570. package/src/storymap/iiif.ts +1742 -95
  571. package/src/storymap/to-iiif.ts +1008 -0
  572. package/src/storymap/validate.ts +80 -7
  573. package/src/types.ts +591 -29
  574. package/src/ui/LayersControl.ts +302 -0
  575. package/src/ui/MenuBar.ts +325 -61
  576. package/src/ui/Message.ts +44 -2
  577. package/src/ui/Swipable.ts +170 -85
  578. package/dist/assets/demo-D6cTmzn6.js +0 -1
  579. package/dist/assets/harness-BPFlzutp.js +0 -1
  580. package/dist/assets/index-DDsPBPZA.js +0 -1
  581. package/dist/assets/main-Y-MYUSJ4.js +0 -17
  582. package/src/animation/morpheus.d.ts +0 -41
  583. package/src/scss/VCO.StoryMap.Dark.scss +0 -138
  584. package/src/scss/Variables.Dark.scss +0 -56
  585. package/src/scss/media/types/VCO.Media.Instagram.scss +0 -7
  586. package/src/scss/media/types/VCO.Media.Profile.scss +0 -5
  587. package/src/ui/Draggable.ts +0 -374
@@ -10,21 +10,71 @@ 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
 
17
- A manifest carries three context URLs: the Presentation 3.0 context, the
18
- official [navPlace extension](https://iiif.io/api/extension/navplace/) context,
19
- and the StoryMap extension context:
21
+ A manifest declares four context URLs, in this order: the official
22
+ [navPlace extension](https://iiif.io/api/extension/navplace/) context (which
23
+ §3.1 of the extension requires before Presentation 3), the Presentation 3.0
24
+ context, the navPlace properties context, and the StoryMap extension context.
25
+ The last of the four resolves to the document below — shown inline here for
26
+ reference; a manifest must reference it by URL, not paste it in (see the
27
+ `@context` rule under "Validator interop"):
20
28
 
21
29
  ```json
22
30
  {
23
- "@context": [
24
- "http://iiif.io/api/presentation/3/context.json",
25
- "http://iiif.io/api/extension/navplace/context.json",
26
- "https://cmahnke.github.io/StoryMapJS/context.json"
27
- ]
31
+ "@context": {
32
+ "@version": 1.1,
33
+ "storymap": "https://christianmahnke.de/iiif/storymap#",
34
+ "mapAsImage": "storymap:mapAsImage",
35
+ "tilejson": "storymap:tilejson",
36
+ "mapAccessToken": "storymap:mapAccessToken",
37
+ "mapBackgroundColor": "storymap:mapBackgroundColor",
38
+ "mapCenterOffset": "storymap:mapCenterOffset",
39
+ "fontCss": "storymap:fontCss",
40
+ "callToAction": "storymap:callToAction",
41
+ "callToActionText": "storymap:callToActionText",
42
+ "startAtSlide": "storymap:startAtSlide",
43
+ "language": "storymap:language",
44
+ "calculateZoom": "storymap:calculateZoom",
45
+ "lineFollowsPath": "storymap:lineFollowsPath",
46
+ "showLines": "storymap:showLines",
47
+ "showHistoryLine": "storymap:showHistoryLine",
48
+ "lineColor": "storymap:lineColor",
49
+ "lineColorInactive": "storymap:lineColorInactive",
50
+ "lineWeight": "storymap:lineWeight",
51
+ "lineOpacity": "storymap:lineOpacity",
52
+ "lineDash": "storymap:lineDash",
53
+ "lineJoin": "storymap:lineJoin",
54
+ "useCustomMarkers": "storymap:useCustomMarkers",
55
+ "mapArea": "storymap:mapArea",
56
+ "overviewExtent": "storymap:overviewExtent",
57
+ "keyboard": "storymap:keyboard",
58
+ "overlays": "storymap:overlays",
59
+ "type": {
60
+ "@id": "storymap:type",
61
+ "@type": "@id"
62
+ },
63
+ "mediaSrcset": "storymap:mediaSrcset",
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"
77
+ }
28
78
  }
29
79
  ```
30
80
 
@@ -59,20 +109,17 @@ what the fixtures reference. Content:
59
109
  "@context": {
60
110
  "@version": 1.1,
61
111
  "storymap": "https://christianmahnke.de/iiif/storymap#",
62
- "mapType": "storymap:mapType",
112
+ "tilejson": "storymap:tilejson",
63
113
  "mapAsImage": "storymap:mapAsImage",
64
114
  "mapAccessToken": "storymap:mapAccessToken",
65
115
  "mapBackgroundColor": "storymap:mapBackgroundColor",
66
116
  "mapCenterOffset": "storymap:mapCenterOffset",
67
- "mapSubdomains": "storymap:mapSubdomains",
68
- "iiifUrl": { "@id": "storymap:iiifUrl", "@type": "@id" },
69
117
  "fontCss": "storymap:fontCss",
70
118
  "callToAction": "storymap:callToAction",
71
119
  "callToActionText": "storymap:callToActionText",
72
120
  "startAtSlide": "storymap:startAtSlide",
73
121
  "language": "storymap:language",
74
122
  "calculateZoom": "storymap:calculateZoom",
75
- "lessBounce": "storymap:lessBounce",
76
123
  "lineFollowsPath": "storymap:lineFollowsPath",
77
124
  "showLines": "storymap:showLines",
78
125
  "showHistoryLine": "storymap:showHistoryLine",
@@ -83,11 +130,25 @@ what the fixtures reference. Content:
83
130
  "lineDash": "storymap:lineDash",
84
131
  "lineJoin": "storymap:lineJoin",
85
132
  "useCustomMarkers": "storymap:useCustomMarkers",
133
+ "mapArea": "storymap:mapArea",
134
+ "overviewExtent": "storymap:overviewExtent",
135
+ "keyboard": "storymap:keyboard",
136
+ "overlays": "storymap:overlays",
86
137
  "type": { "@id": "storymap:type", "@type": "@id" },
87
- "background": "storymap:background",
88
- "mediaCaption": "storymap:mediaCaption",
89
- "mediaCredit": "storymap:mediaCredit",
90
- "date": "storymap:date"
138
+ "mediaSrcset": "storymap:mediaSrcset",
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"
91
152
  }
92
153
  }
93
154
  ```
@@ -114,19 +175,20 @@ Each slide becomes one Canvas in `items` order. Canvas ids are
114
175
  (`<canvas-id>/annotationpage/1`) holding the slide's painted media
115
176
  (`<canvas-id>/annotation/1`, `motivation: "painting"`, `target: <canvas-id>`).
116
177
 
117
- | IIIF | StoryMap | Notes |
118
- | ----------------------- | --------------------- | ---------------------------------------------------------------------------------------- |
119
- | `id`, `type` | — | `"Canvas"` |
120
- | `label` | `slide.text.headline` | Language map `{"none": [headline]}`; omitted when the headline is empty |
121
- | `summary` | `slide.text.text` | Language map; the slide body text (may contain HTML) |
122
- | `height`, `width` | — | Nominal `1080 × 1080` for non-image slides; actual image dimensions for image-map slides |
123
- | `items` | `slide.media` | AnnotationPage with the painting annotation, see below |
124
- | `storymap:type` | `slide.type` | `"overview"` marks the map overview slide |
125
- | `storymap:background` | `slide.background` | `{url, color}` — only present keys |
126
- | `storymap:mediaCaption` | `slide.media.caption` | |
127
- | `storymap:mediaCredit` | `slide.media.credit` | |
128
- | `storymap:date` | `slide.date` | String or object, verbatim |
129
- | `navPlace` | `slide.location` | See below |
178
+ | IIIF | StoryMap | Notes |
179
+ | ---------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------ |
180
+ | `id`, `type` | — | `"Canvas"` |
181
+ | `label` | `slide.text.headline` | Language map `{"none": [headline]}`; omitted when the headline is empty |
182
+ | `summary` | `slide.text.text` | Language map; the slide body text (may contain HTML) |
183
+ | `height`, `width` | — | Nominal `1080 × 1080` for non-image slides; actual image dimensions for image-map slides |
184
+ | `items` | `slide.media` | AnnotationPage with the painting annotation, see below — which also carries the caption, credit and alt text |
185
+ | `storymap:type` | `slide.type` | `"overview"` marks the map overview slide |
186
+ | `background` | `slide.background` | A painting annotation whose body is an `Image` (the url) and/or a `Color` (the colour) |
187
+ | `storymap:mediaSrcset` | `slide.media.srcset` | Responsive image candidates, passed through to the `img` element |
188
+ | `storymap:mediaSizes` | `slide.media.sizes` | The `sizes` companion of `mediaSrcset` |
189
+ | _(target selector)_ | `slide.location.region` | `ImageApiSelector` `xywh=pixel:x,y,w,h`; image stops on image-map slides |
190
+ | `navDate` | `slide.date` | Plain string, verbatim; the official validator applies no format rule at all, so a human date is fine |
191
+ | `navPlace` | `slide.location` | See below |
130
192
 
131
193
  ## Locations via navPlace
132
194
 
@@ -139,11 +201,54 @@ with one GeoJSON Feature:
139
201
  verbatim. For image-map storymaps (`storymap:mapAsImage: true`) the values are
140
202
  image coordinates rather than WGS84 degrees; consumers can detect this via
141
203
  `storymap:mapAsImage`.
142
- - `properties`: marker data — `zoom`, `line`, `icon`, `iconSize`, `image`,
143
- `use_custom_marker`, `name` (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.
144
214
  - `location.use_custom_marker` / `use_custom_markers` (manifest) opt into
145
215
  custom marker rendering; see the storymap terms below.
146
216
 
217
+ Those properties are described by **`https://cmahnke.github.io/StoryMapJS/navplace-properties.json`**,
218
+ which a manifest using a `properties` bag should name in its `@context`. The
219
+ extension requires it (§3.2): terms in a GeoJSON Feature's `properties` must be
220
+ described either by a registered IIIF extension or by a local linked-data
221
+ context, and a client that meets a property it does not understand must ignore
222
+ it. There is no IIIF extension for marker presentation — navPlace defines
223
+ exactly one term, `navPlace` itself — so the local context is the only option.
224
+ It is why `popup` and `audioBadge` need no `storymap:` term of their own, and
225
+ the same mechanism serves marker config. The thirteen local names hang off this project's existing namespace
226
+ (`https://christianmahnke.de/iiif/storymap#`), not a new one.
227
+
228
+ ### Context order matters
229
+
230
+ The navPlace extension's context **must be listed before** the Presentation 3
231
+ context — §3.1 of the extension:
232
+
233
+ > The navPlace extension linked data context must be included before the IIIF
234
+ > Presentation API 3 linked data context on the top-level object.
235
+
236
+ So a manifest that uses `navPlace` declares:
237
+
238
+ ```json
239
+ "@context": [
240
+ "http://iiif.io/api/extension/navplace/context.json",
241
+ "http://iiif.io/api/presentation/3/context.json",
242
+ "https://cmahnke.github.io/StoryMapJS/navplace-properties.json",
243
+ "https://cmahnke.github.io/StoryMapJS/context.json"
244
+ ]
245
+ ```
246
+
247
+ Getting this backwards does not break a viewer — the reader does not consult
248
+ either context — but it does make the document wrong as linked data, which is
249
+ the point of shipping a context at all. Every fixture in this repository had it
250
+ backwards.
251
+
147
252
  Alternatively a manifest MAY aggregate all slide locations in a single
148
253
  manifest-level `navPlace` with one Feature per Canvas in `items` order.
149
254
 
@@ -201,7 +306,7 @@ actual image dimensions. Two body variants are valid:
201
306
  ```
202
307
 
203
308
  The converter emits variant (b). Legacy `zoomify` storymaps are converted to
204
- `storymap:mapType: "iiif"`; since the original zoomify tile paths are dead, the
309
+ `storymap:basemap: "iiif"`; since the original zoomify tile paths are dead, the
205
310
  converter substitutes the IIIF reference image above (the legacy pyramid
206
311
  definition is not carried — nothing reads it).
207
312
 
@@ -222,51 +327,401 @@ properties):
222
327
  {
223
328
  "id": "https://example.org/storymap/<name>/map-config",
224
329
  "type": "Service",
225
- "profile": "https://christianmahnke.de/iiif/storymap/mapconfig",
226
- "storymap:mapType": "osm:standard"
330
+ "profile": "https://cmahnke.github.io/StoryMapJS/context.json/mapconfig",
331
+ "storymap:basemap": "osm:standard"
332
+ }
333
+ ]
334
+ }
335
+ ```
336
+
337
+ ### TileJSON for a tile service
338
+
339
+ A keyword basemap and a tile URL template are different kinds of thing, and
340
+ `mapType` used to be both. They are now separate: `storymap:basemap` names a
341
+ source the viewer knows how to configure, and an **unprefixed** `tilejson`
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
345
+ `tiles` is required:
346
+
347
+ ```json
348
+ {
349
+ "service": [
350
+ {
351
+ "id": "https://example.org/storymap/<name>/map-config",
352
+ "type": "Service",
353
+ "profile": "https://cmahnke.github.io/StoryMapJS/context.json/mapconfig",
354
+ "tilejson": {
355
+ "tiles": ["https://tiles.example.org/{z}/{x}/{y}.png"],
356
+ "minzoom": 4,
357
+ "maxzoom": 17,
358
+ "bounds": [-122.7, 37.1, -121.1, 38.1],
359
+ "scheme": "tms",
360
+ "center": [4.4777, 51.9244, 12]
361
+ }
362
+ // `tiles` may also be a single template string — that is what the
363
+ // converter writes. The reader accepts both forms.
227
364
  }
228
365
  ]
229
366
  }
230
367
  ```
231
368
 
232
- | Service property (storymap:) | StoryMap field | Values |
233
- | ---------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
234
- | `mapType` | `map_type` | `osm:standard`, `mapbox:...`, `stadia:...`, `iiif`, or an `https://...` tile URL; `zoomify` is replaced by `iiif` |
235
- | `mapAsImage` | `map_as_image` | `true` when the image itself is the map |
236
- | `mapAccessToken` | `map_access_token` | Mapbox/Stadia token from the storymap data, never the repository |
237
- | `mapBackgroundColor` | `map_background_color` | CSS color |
238
- | `mapCenterOffset` | `map_center_offset` | `{left, top}` |
239
- | `mapSubdomains` | `map_subdomains` | Tile URL subdomains |
240
- | `iiifUrl` | `iiif.url` | IIIF Image API `info.json` URL for image-map storymaps |
241
- | `fontCss` | `font_css` | e.g. `stock:dancing-ledger` |
242
- | `callToAction` | `call_to_action` | boolean |
243
- | `callToActionText` | `call_to_action_text` | string |
244
- | `startAtSlide` | `start_at_slide` | 0-based slide index |
245
- | `language` | `language` | IETF language tag |
246
- | `calculateZoom` | `calculate_zoom` | boolean |
247
- | `lessBounce` | `less_bounce` | boolean |
248
- | `lineFollowsPath` | `line_follows_path` | boolean |
249
- | `showLines` | `show_lines` | boolean |
250
- | `showHistoryLine` | `show_history_line` | boolean |
251
- | `lineColor` | `line_color` | CSS color |
252
- | `lineColorInactive` | `line_color_inactive` | CSS color |
253
- | `lineWeight` | `line_weight` | number (px) |
254
- | `lineOpacity` | `line_opacity` | 0–1 |
255
- | `lineDash` | `line_dash` | CSS dash pattern |
256
- | `lineJoin` | `line_join` | CSS line join |
257
- | `useCustomMarkers` | `use_custom_markers` | boolean |
369
+ `tiles` becomes `map_type`, so everything that dispatches on a template (the
370
+ `tile_source_factory` option, attribution, the minimap) works unchanged. The
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`:
374
+
375
+ | Member | Effect |
376
+ | --------- | ------------------------------------------------------------------------- |
377
+ | `tiles` | the tile URL template, as `map_type` |
378
+ | `minzoom` | the view's minimum zoom, and the tile grid's range |
379
+ | `maxzoom` | the view's maximum zoom, and the tile grid's range |
380
+ | `bounds` | a `[west, south, east, north]` lon/lat box the view center is kept inside |
381
+ | `scheme` | `tms` flips the tile row, which is counted from the bottom in TMS |
382
+ | `center` | `[lon, lat, zoom]`, the initial view |
383
+
384
+ The `center` is the initial view only, and `bounds` constrains the center
385
+ without pinning the resolution — a hard extent constraint would fight the panel
386
+ offset, the same reason `map_bbox` works the way it does.
387
+
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 |
258
421
 
259
422
  ### Canvas level — direct properties
260
423
 
261
424
  Canvas objects are open for extension terms, so slide-specific StoryMap data is
262
- carried directly on the Canvas: `storymap:type`, `storymap:background`,
263
- `storymap:mediaCaption`, `storymap:mediaCredit`, `storymap:date` (see the
264
- Canvas table above).
425
+ carried directly on the Canvas: `storymap:type`, plus the two terms with no
426
+ standard home, `storymap:mediaSrcset` and `storymap:mediaSizes` (see the
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
435
+ background is the standard `background` annotation. The media caption, credit and alt
436
+ text are **not** terms any more: they are the painting annotation's own `label`,
437
+ `requiredStatement` and `accessibilitySummary`, which is where Presentation 3
438
+ defines them. A manifest written against the old terms still loads — the strings
439
+ are simply no longer read.
265
440
 
266
441
  Readers must use the prefixed term for the slide type (`storymap:type`): the
267
442
  bare `type` key of a Canvas is the IIIF class type (`"Canvas"`) and can never
268
443
  carry the StoryMap slide type.
269
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
+
461
+ ## Annotation-driven tour stops
462
+
463
+ A Canvas annotation whose `motivation` is `commenting`, `tagging`,
464
+ `classifying` or `describing` and whose target resolves to a region becomes
465
+ one slide, appended after that Canvas's own slide. This is the shape Storiiies
466
+ and Micrio use for a guided tour of one image, and it is the subject of
467
+ [docs/iiif-authoring.md](iiif-authoring.md).
468
+
469
+ - **Target** — `xywh=` fragment / Image API Selector, or a `PointSelector`
470
+ (synthesized into a square of 5% of the Canvas's smaller side, centred and
471
+ clamped). A `TextQuoteSelector`, `TimeState` or `SvgSelector` is preserved
472
+ but not resolved or drawn. A bare string target's `#xywh=` counts. An
473
+ annotation aimed at the whole Canvas is **not** a stop.
474
+ - **Body** — a `TextualBody` supplies the slide text (`text/plain` escaped and
475
+ split per blank-line block, `text/html` kept as markup); a body with an
476
+ `id` (e.g. `type: "Sound"`) supplies `media.url`, whose extension picks the
477
+ player. An annotation with a region but no body is not a stop.
478
+ - **Region stops are honoured in image mode** only — the same rule as a
479
+ `xywh=pixel:` region. A geographic map ignores them.
480
+ - `navPlace` may not appear on an Annotation (the extension forbids it), so
481
+ all stops on a Canvas share that Canvas's location and marker presentation.
482
+
483
+ ## What the body record carries
484
+
485
+ The painting annotation's body is read into one shared record. The
486
+ `storymap:mediaCaption` / `mediaCredit` / `mediaAlt` extension terms are
487
+ dropped — a manifest still using them loads, but the strings are not read —
488
+ and the standard properties are the only source:
489
+
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) |
499
+
500
+ ## Native IIIF vs. the StoryMap extension
501
+
502
+ IIIF defines three approved Presentation API extensions — navPlace, Text
503
+ Granularity and Georeference — and **no vocabulary for a basemap or a tile
504
+ layer stack**. Everything the viewer draws under and over the story (basemap
505
+ type, layout, minimap bounds, stacked layers, keyboard navigation) therefore
506
+ stays in the `storymap:` terms of the map configuration service, which is the
507
+ JSON-LD-idiomatic place for extended configuration. What IIIF _does_ model
508
+ natively is used wherever it exists:
509
+
510
+ | Story | Native IIIF | Used here |
511
+ | -------------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------- |
512
+ | Slide location | `navPlace` Point | yes |
513
+ | Story extent | `navPlace` Polygon (an explicit navPlace use case) | yes — a canvas polygon becomes `map_bbox` |
514
+ | Image region stops | `ImageApiSelector` `xywh=pixel:` on the painting annotation target | yes — the selector is the only source (§2.8) |
515
+ | Raster layer placed on a map | [Georeference Extension](https://iiif.io/api/extension/georef) (GCPs, `motivation: "georeferencing"`) | yes — see below |
516
+ | Basemap, layer stack, layout, keyboard | — | no; `storymap:` terms |
517
+
518
+ ### Groups and the slide order
519
+
520
+ `structures` does two jobs. A Range with a `label` and no `start` is a **group**,
521
+ and every canvas it contains gets that value as `slide.group`; nested Ranges are
522
+ chapters inside it, and the outermost labelled Range is the group. And the order
523
+ canvases appear in is the **slide order** — a Range is allowed to run them in a
524
+ order the document does not, which is what a storyboard is for:
525
+
526
+ ```json
527
+ {
528
+ "structures": [
529
+ {
530
+ "id": "https://example.org/storymap/<name>/range/1",
531
+ "type": "Range",
532
+ "label": { "none": ["Act I"] },
533
+ "items": [
534
+ "https://example.org/storymap/<name>/canvas/1",
535
+ "https://example.org/storymap/<name>/canvas/3"
536
+ ]
537
+ }
538
+ ]
539
+ }
540
+ ```
541
+
542
+ A canvas in no Range keeps its document position, after the ones a Range does
543
+ mention. A Range with a `start` is a time segment of a canvas, not a group: it
544
+ contributes order and nothing else.
545
+
546
+ ### Deep links and external annotations
547
+
548
+ Two things a manifest can offer that a viewer used to ignore.
549
+
550
+ **A stop can be linked by its identity.** Every canvas id is a `uniqueid`
551
+ (§2.3), so a stop is addressable by something that survives a slide being
552
+ inserted above it. The viewer writes both forms:
553
+
554
+ | Where | Form | Example |
555
+ | ---------------- | ------------------------------------------------------------ | ------------------------------------- |
556
+ | `change` payload | `current_id`, next to `current_slide` | — |
557
+ | URL hash | `#slide-<uniqueid>`, or `#slide-3` for a storymap-JSON slide | `#slide-https%3A%2F%2F…%2Fcanvas%2F3` |
558
+ | Query parameter | `iiif-content`, IIIF Content State 1.0 | `?iiif-content=https://…/canvas/3` |
559
+
560
+ Both are read on load, and the hash again on every `hashchange`, so browser
561
+ back/forward keeps working. The index form is still accepted, so links shared
562
+ before ids were emitted keep resolving.
563
+
564
+ The `iiif-content` parameter is the standard's own format and follows its
565
+ encoding rule, which is deliberately asymmetric: a **plain URI is written
566
+ unencoded**, a **JSON-LD form is content-state-encoded** (base64url, no
567
+ padding). A whole canvas is therefore a bare target URI, while a region — which
568
+ the spec says a bare URI cannot express — is the encoded Target Body:
569
+
570
+ ```json
571
+ {
572
+ "target": {
573
+ "type": "SpecificResource",
574
+ "source": { "id": "https://example.org/canvas/7", "type": "Canvas" },
575
+ "selector": { "type": "ImageApiSelector", "value": "xywh=pixel:10,20,30,40" }
576
+ }
577
+ }
578
+ ```
579
+
580
+ **External annotations.** A manifest's `seeAlso` points at annotation
581
+ collections or pages that live on an annotation server. They are recorded on the
582
+ data as `see_also` but **not fetched** — reading them is a network round trip
583
+ per document, and a viewer should not block its first paint on a third party. A
584
+ host opts in:
585
+
586
+ ```js
587
+ const { stops, searchService, failed } = await storymap.loadAnnotations();
588
+ ```
589
+
590
+ which fetches, merges the annotations for the canvases being rendered into tour
591
+ stops, and fires `annotationsloaded` with the same value. A `SearchService1` in
592
+ `seeAlso` is reported as `searchService` rather than followed. One level of
593
+ indirection is followed, so a collection may reference its pages, but a cycle
594
+ cannot become an infinite walk. Fetching is cached per document, so two calls
595
+ share one request.
596
+
597
+ ### Institutional credit
598
+
599
+ A manifest says who published it and under what licence, and all of it ends up
600
+ on the one credit line the viewer renders — the map attribution the host can
601
+ also feed with `setExtraAttributions()`:
602
+
603
+ | Manifest property | Becomes |
604
+ | ------------------- | ----------------------------------- |
605
+ | `requiredStatement` | `Attribution: <value>` |
606
+ | `provider` (Agent) | `Provider: <label, or the id>` |
607
+ | `rights` | `Licence: <uri>` |
608
+ | `homepage` (Agent) | the Agent's label or id, unlabelled |
609
+
610
+ They are joined with `·` in that order. `logo` is an image rather than a
611
+ credit line, so it is offered as `data.logo`, and `metadata`'s label/value
612
+ pairs are handed on as `data.metadata[]` — arbitrary pairs cannot be rendered
613
+ generically, and dropping them loses provenance.
614
+
615
+ The converter writes a `metadata` pair reading "Generated by: StoryMapJS"
616
+ rather than claiming to be the manifest's `provider`. P3's `provider` is
617
+ whoever published the content, and the converter does not know that; writing
618
+ itself there would put "Provider: StoryMapJS" on the credit line of every
619
+ converted storymap.
620
+
621
+ ### Geo-referenced layers
622
+
623
+ A `motivation: "georeferencing"` annotation carries the Georeference Extension
624
+ payload: the IIIF Image API service to place in its `target`, and its ground
625
+ control points (`properties.resourceCoords` ↔ `geometry.coordinates`, WGS84) in
626
+ its `body`. Per the extension, a layer that is not part of the canvas it ships
627
+ in — which is every map layer — embeds the image it places in `target` rather
628
+ than referencing it. The viewer fits the points affinely and places the image,
629
+ which OpenLayers reprojects onto the view exactly like the IIIF basemap:
630
+
631
+ ```json
632
+ {
633
+ "items": [
634
+ {
635
+ "id": "https://example.org/storymap/<name>/canvas/1",
636
+ "type": "Canvas",
637
+ "items": [
638
+ {
639
+ "id": "https://example.org/storymap/<name>/canvas/1/georeferencing/1",
640
+ "type": "Annotation",
641
+ "motivation": "georeferencing",
642
+ "target": {
643
+ "id": "https://iiif.example.org/image1",
644
+ "type": "Image",
645
+ "width": 5965,
646
+ "height": 2514,
647
+ "service": [
648
+ {
649
+ "id": "https://iiif.example.org/image1",
650
+ "type": "ImageService3",
651
+ "profile": "level2"
652
+ }
653
+ ]
654
+ },
655
+ "requiredStatement": {
656
+ "label": { "none": ["Attribution"] },
657
+ "value": { "none": ["Sheet 12, 1789"] }
658
+ },
659
+ "body": {
660
+ "type": "FeatureCollection",
661
+ "transformation": { "type": "polynomial", "options": { "order": 1 } },
662
+ "features": [
663
+ {
664
+ "type": "Feature",
665
+ "properties": { "resourceCoords": [5085, 782] },
666
+ "geometry": {
667
+ "type": "Point",
668
+ "coordinates": [4.4885839, 51.9101828]
669
+ }
670
+ }
671
+ ]
672
+ }
673
+ }
674
+ ]
675
+ }
676
+ ]
677
+ }
678
+ ```
679
+
680
+ An annotation is canvas-scoped but the layer it describes is map-wide, so the
681
+ annotations are collected from **every** canvas: a layer annotated on the first
682
+ canvas still applies to the whole story. `requiredStatement` is read as the
683
+ layer's attribution. The other presentation keys the term could carry —
684
+ `opacity`, `visible`, `className`, `blendMode` — have no IIIF vocabulary for a
685
+ georeferencing annotation and are not read; the extent is not lost in substance,
686
+ because the control points describe it. Entries with fewer than three usable
687
+ points are dropped while reading.
688
+
689
+ **A caveat about the official validator.** The Presentation 3.0 validator checks
690
+ against the base JSON Schema, which predates the Georeference Extension, so it
691
+ rejects a `FeatureCollection` body and an embedded `Image` target with _"is not
692
+ valid under any of the given schemas"_ — even with the extension's own context
693
+ declared, which does resolve at
694
+ `http://iiif.io/api/extension/georef/1/context.json`. We keep the extension's
695
+ spelling anyway: a georeferenced manifest that other IIIF tools can read is
696
+ worth more than one this particular validator accepts. `npm run validate:iiif`
697
+ reports the two georeferenced fixtures as _not covered_ rather than as failures,
698
+ with that reason.
699
+
700
+ The result is an `overlays[]` entry, so `setOverlayVisible()` /
701
+ `setOverlayOpacity()` and the rest of the layer API work on it as for any other
702
+ layer. A storymap-JSON `overlays[]` entry may carry a `georeference` in place
703
+ of a `map_type`, which is the shape the converter writes these annotations
704
+ from.
705
+
706
+ **Limits.** The extension also allows second/third-order polynomials, thin
707
+ plate splines and rotated or skewed sheets. OpenLayers places an image as an
708
+ axis-aligned extent, so the viewer fits the affine (first-order) case only:
709
+ anything else is reported in the console and skipped rather than drawn in the
710
+ wrong place. For true warping, plug
711
+ [Allmaps' `WarpedMapLayer`](https://www.npmjs.com/package/@allmaps/openlayers)
712
+ (or any OpenLayers layer) into the `tile_source_factory` option and keep the
713
+ georeference data on your side — see the "IIIF extensions" recipe in
714
+ [docs/migration-from-knightlab.md](migration-from-knightlab.md). Image-space
715
+ maps (`map_as_image`, zoomify) have no geographic view, so a placed sheet is
716
+ skipped there as well.
717
+
718
+ A storymap-JSON `overlays[]` entry can carry a `georeference` — url, width,
719
+ height and the FeatureCollection body — instead of a `map_type`, and the
720
+ converter writes it as the annotation above, on the first canvas. The two
721
+ georeferenced fixtures are still hand-authored: they are the only manifests in
722
+ the set with no storymap-JSON source. `georeferenced-layer.json` places its
723
+ sheet; `georeferenced-layer-unsupported.json` shows the skip path.
724
+
270
725
  ## Validator interop
271
726
 
272
727
  The official IIIF presentation validator
@@ -292,8 +747,9 @@ photo, and a slide with a YouTube video — full manifest:
292
747
  ```json
293
748
  {
294
749
  "@context": [
295
- "http://iiif.io/api/presentation/3/context.json",
296
750
  "http://iiif.io/api/extension/navplace/context.json",
751
+ "http://iiif.io/api/presentation/3/context.json",
752
+ "https://cmahnke.github.io/StoryMapJS/navplace-properties.json",
297
753
  "https://cmahnke.github.io/StoryMapJS/context.json"
298
754
  ],
299
755
  "id": "https://example.org/storymap/storm",
@@ -311,8 +767,8 @@ photo, and a slide with a YouTube video — full manifest:
311
767
  {
312
768
  "id": "https://example.org/storymap/storm/map-config",
313
769
  "type": "Service",
314
- "profile": "https://christianmahnke.de/iiif/storymap/mapconfig",
315
- "storymap:mapType": "osm:standard",
770
+ "profile": "https://cmahnke.github.io/StoryMapJS/context.json/mapconfig",
771
+ "storymap:basemap": "osm:standard",
316
772
  "storymap:language": "en",
317
773
  "storymap:showLines": true,
318
774
  "storymap:showHistoryLine": true,
@@ -349,7 +805,7 @@ photo, and a slide with a YouTube video — full manifest:
349
805
  }
350
806
  ],
351
807
  "storymap:type": "overview",
352
- "storymap:date": "Sep 1"
808
+ "navDate": "Sep 1"
353
809
  },
354
810
  {
355
811
  "id": "https://example.org/storymap/storm/canvas/2",
@@ -372,14 +828,17 @@ photo, and a slide with a YouTube video — full manifest:
372
828
  "type": "Image",
373
829
  "format": "image/jpeg"
374
830
  },
375
- "target": "https://example.org/storymap/storm/canvas/2"
831
+ "target": "https://example.org/storymap/storm/canvas/2",
832
+ "label": "Landfall",
833
+ "requiredStatement": {
834
+ "label": { "none": ["Credit"] },
835
+ "value": { "none": ["Weather Service"] }
836
+ }
376
837
  }
377
838
  ]
378
839
  }
379
840
  ],
380
- "storymap:mediaCaption": "Landfall",
381
- "storymap:mediaCredit": "Weather Service",
382
- "storymap:date": "Sep 2",
841
+ "navDate": "Sep 2",
383
842
  "navPlace": {
384
843
  "id": "https://example.org/storymap/storm/canvas/2/navplace",
385
844
  "type": "FeatureCollection",
@@ -412,13 +871,16 @@ photo, and a slide with a YouTube video — full manifest:
412
871
  "id": "https://www.youtube.com/watch?v=example",
413
872
  "type": "Video"
414
873
  },
415
- "target": "https://example.org/storymap/storm/canvas/3"
874
+ "target": "https://example.org/storymap/storm/canvas/3",
875
+ "requiredStatement": {
876
+ "label": { "none": ["Credit"] },
877
+ "value": { "none": ["News"] }
878
+ }
416
879
  }
417
880
  ]
418
881
  }
419
882
  ],
420
- "storymap:mediaCredit": "News",
421
- "storymap:date": "Sep 3",
883
+ "navDate": "Sep 3",
422
884
  "navPlace": {
423
885
  "id": "https://example.org/storymap/storm/canvas/3/navplace",
424
886
  "type": "FeatureCollection",
@@ -438,73 +900,108 @@ photo, and a slide with a YouTube video — full manifest:
438
900
 
439
901
  ## Full mapping table
440
902
 
441
- | Legacy field (storymap root) | IIIF path |
442
- | ---------------------------- | ------------------------------------------------------------------- |
443
- | `slides` | `items[]` (Canvas per slide) |
444
- | `language` | `service[0].storymap:language` |
445
- | `map_type` | `service[0].storymap:mapType` (`zoomify` → `iiif`) |
446
- | `map_as_image` | `service[0].storymap:mapAsImage` |
447
- | `map_mini` | _dropped_ (viewer setting, not part of the exchange format) |
448
- | `map_subdomains` | `service[0].storymap:mapSubdomains` |
449
- | `map_access_token` | `service[0].storymap:mapAccessToken` |
450
- | `map_background_color` | `service[0].storymap:mapBackgroundColor` |
451
- | `map_center_offset` | `service[0].storymap:mapCenterOffset` |
452
- | `map_popup` | _dropped_ (viewer setting) |
453
- | `use_custom_markers` | `service[0].storymap:useCustomMarkers` |
454
- | `zoom_distance` | _dropped_ (viewer setting) |
455
- | `calculate_zoom` | `service[0].storymap:calculateZoom` |
456
- | `less_bounce` | `service[0].storymap:lessBounce` |
457
- | `line_follows_path` | `service[0].storymap:lineFollowsPath` |
458
- | `show_lines` | `service[0].storymap:showLines` |
459
- | `show_history_line` | `service[0].storymap:showHistoryLine` |
460
- | `line_color` | `service[0].storymap:lineColor` |
461
- | `line_color_inactive` | `service[0].storymap:lineColorInactive` |
462
- | `line_weight` | `service[0].storymap:lineWeight` |
463
- | `line_opacity` | `service[0].storymap:lineOpacity` |
464
- | `line_dash` | `service[0].storymap:lineDash` |
465
- | `line_join` | `service[0].storymap:lineJoin` |
466
- | `iiif.url` | `service[0].storymap:iiifUrl` + canvas Image annotation `service[]` |
467
- | `iiif.attribution` | `requiredStatement` |
468
- | `zoomify` | _dropped_ (zoomify is replaced by the IIIF reference image) |
469
- | `font_css` | `service[0].storymap:fontCss` |
470
- | `call_to_action` | `service[0].storymap:callToAction` |
471
- | `call_to_action_text` | `service[0].storymap:callToActionText` |
472
- | `relative_date` | _dropped_ (viewer setting) |
473
- | `start_at_slide` | `service[0].storymap:startAtSlide` |
474
- | _(root) `width`, `height`_ | _dropped_ (viewer embed size) |
475
-
476
- | Legacy field (slide) | IIIF path |
477
- | ------------------------------ | ---------------------------------------------------------- |
478
- | `type: "overview"` | Canvas `storymap:type: "overview"` |
479
- | `date` | Canvas `storymap:date` |
480
- | `text.headline` | Canvas `label` (language map) |
481
- | `text.text` | Canvas `summary` (language map) |
482
- | `location.lat`, `location.lon` | Canvas `navPlace` Feature `geometry.coordinates` |
483
- | `location.zoom` | Canvas `navPlace` Feature `properties.zoom` |
484
- | `location.line` | Canvas `navPlace` Feature `properties.line` |
485
- | `location.name` | Canvas `navPlace` Feature `properties.name` |
486
- | `location.icon` | Canvas `navPlace` Feature `properties.icon` |
487
- | `location.iconSize` | Canvas `navPlace` Feature `properties.iconSize` |
488
- | `location.image` | Canvas `navPlace` Feature `properties.image` |
489
- | `location.use_custom_marker` | Canvas `navPlace` Feature `properties.use_custom_marker` |
490
- | `media.url` (image) | Annotation body `{type: "Image", format: ...}` |
491
- | `media.url` (video service) | Annotation body `{type: "Video"}` |
492
- | `media.url` (audio service) | Annotation body `{type: "Sound"}` |
493
- | `media.url` (web page) | Annotation body `{type: "Text", format: "text/html"}` |
494
- | `media.url` (absent / HTML) | Annotation body `{type: "TextualBody", value: ...}` |
495
- | `media.caption` | Canvas `storymap:mediaCaption` |
496
- | `media.credit` | Canvas `storymap:mediaCredit` |
497
- | `media.thumb` | _dropped_ (thumbnails may be added via Canvas `thumbnail`) |
498
- | `background` | Canvas `storymap:background` `{url, color}` |
499
- | `uniqueid` | _dropped_ (canvas `id`s are the canonical identifiers) |
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) |
500
988
 
501
989
  ## Conversion
502
990
 
503
- `node scripts/convert-to-iiif.mjs` regenerates `public/examples-iiif/` from
504
- `public/examples/`. Ids are deterministic:
991
+ `npm run convert:iiif` regenerates `public/examples-iiif/` from
992
+ `public/examples/` (it needs Node 22.6+, since the script imports the
993
+ TypeScript library source via type stripping). Ids are deterministic:
505
994
 
506
995
  - Manifest: `https://example.org/storymap/<name>`
507
996
  - Canvas: `<manifest-id>/canvas/<n>` (1-based, slide order)
508
997
  - AnnotationPage: `<canvas-id>/annotationpage/1`
509
998
  - Annotation: `<canvas-id>/annotation/1`
510
999
  - FeatureCollection / Feature: `<canvas-id>/navplace[.../feature/1]`
1000
+
1001
+ Three fixtures in `public/examples-iiif/` are hand-authored and not
1002
+ overwritten by a full run: `georeferenced-layer.json` and
1003
+ `georeferenced-layer-unsupported.json`, which exercise the Georeference
1004
+ Extension payloads (the legacy format cannot express ground control points,
1005
+ so there is nothing to convert from), and `annotated-image.json`, the
1006
+ annotation-driven tour (there is no storymap document to convert from —
1007
+ annotation stops only exist on the manifest side).