@projektemacher/storymapjs 0.10.6 → 0.10.8

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