@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
package/CHANGELOG CHANGED
@@ -1,10 +1,304 @@
1
- 1.0.0 (unreleased)
1
+ 0.10.8 (2026-09-29)
2
2
  ------------------------
3
- Viewer-only restructure of the repository:
3
+ Code audit: one regression, a set of latent bugs, seven stored-XSS sinks, a
4
+ disabled type check that had been hiding them, and a dependency swap.
5
+
6
+ Added
7
+ -----
8
+ - **`map_type: "none"`: a storymap with no map.** The text and the media are
9
+ the whole story, which the map's unconditional construction used to make
10
+ impossible. No `ol/Map` is built, so there is no tile request to consent to
11
+ and the consent dialog omits its tile row; the overview control is hidden;
12
+ the slider panel takes the full width, since there is no map to fade over;
13
+ and `loaded` fires without waiting for a map that will never load. The
14
+ accessors return their neutral values and the map setters are no-ops.
15
+ `map_type: ""` and an absent key still mean OpenStreetMap, and `map_type:
16
+ null` is normalised to that default instead of throwing out of the
17
+ constructor (the schema already allowed the key to be missing)
18
+ - **`storymapToManifest()` is now a library export**, promoted out of the
19
+ `convert:iiif` script, so one function both writes and reads the IIIF format
20
+ and a host can produce a manifest in the browser. The CLI delegates to it
21
+ (via Node's own type stripping, so no new dependency and no build step), and
22
+ its output is unchanged byte for byte across all 50 fixtures
23
+ - **Annotation-driven tour stops.** A IIIF manifest whose commenting,
24
+ tagging, classifying or describing annotations carry a fragment target
25
+ becomes one slide per annotation, each fitting the region it points at —
26
+ the Storiiies/Micrio shape. `text/plain` bodies become one paragraph per
27
+ block (escaped), `text/html` keeps its markup, and a `Sound` body becomes
28
+ the slide's media. A `PointSelector` becomes a square of 5% of the
29
+ canvas's smaller side, centred and clamped. New `docs/iiif-authoring.md`
30
+ (published as `authoring.html`) and a four-stop example,
31
+ `public/examples-iiif/annotated-image.json`
32
+ - A normalized selector reader: `FragmentSelector`/`ImageApiSelector`
33
+ (`xywh=`, including `xywh=pixel:`), `PointSelector`, `TextQuoteSelector`,
34
+ `TimeState` and `SvgSelector` are all read, one level of `refinedBy` is
35
+ followed, and a string target's `#xywh=` fragment counts. Quote and SVG
36
+ selectors are preserved but not yet resolved or drawn — the guide says so
37
+ - The painting body's standard fields are the only source for the slide
38
+ media record: `body.label` (caption), `body.requiredStatement` /
39
+ `body.provider` (credit), `body.accessibilitySummary` (alt),
40
+ `body.thumbnail` (thumb), and a `TextualBody` with `format: text/vtt`
41
+ (subtitles). The `storymap:mediaCaption` / `mediaCredit` / `mediaAlt`
42
+ extension terms are dropped; a manifest still using them loads, but the
43
+ strings are no longer read
44
+ (subtitles)
45
+ - `media.subtitles`: a WebVTT file rendered as a `<track kind="subtitles">`
46
+ on the audio or video element
47
+ - Per-slide `narration: {url}`, played through one reused audio element
48
+ rather than the slide's media frame, so switching slides cannot leave a
49
+ recording playing. Gated by browser autoplay policy (it starts after the
50
+ first gesture) and by a new `media:narration` consent service, so the GDPR
51
+ mode has no hole for it
52
+ - `autoplay_media`: with autoplay on, a slide whose media is audio or video
53
+ advances when it ends instead of on the millisecond timer. The timer stays
54
+ armed as a fallback, so a media element that never fires `ended` cannot
55
+ stall the story
56
+ - Per-slide `marker: { icon, iconSize, image, label, popup, audioBadge }`,
57
+ with `location.*` kept as the legacy spelling and `marker.*` winning. No
58
+ new `storymap:` term: in a manifest all of it arrives in the `navPlace`
59
+ Feature `properties` bag, which is a GeoJSON foreign-member bag and needs
60
+ no vocabulary registration
61
+ - `marker.popup`: the active marker's card toggles on click, with a sanitized
62
+ headline and excerpt, the media thumb and a real close button. Escape and
63
+ navigating away both close it, and the marker releases it (and its keydown
64
+ listener) in `dispose()`. Inactive markers still navigate on click
65
+ - `marker.audioBadge`: a dot on markers whose slide has narration or audio
66
+ media
67
+ - Browser coverage for the surfaces jsdom cannot reach, and for the changes
68
+ that came with replacing the map engine: `imageready` against a real
69
+ asynchronously-attached IIIF source, `dispose()` proving no tile requests
70
+ happen after teardown, `addTo()`/`removeFrom()` re-measuring a moved map,
71
+ the `isImageSpace()` contract, runtime option and language changes,
72
+ per-viewer consent, `tile_source_factory`, and network-level proof that
73
+ imagery actually reaches the map (the fixture sweep only checked that a
74
+ container existed, so a grey map used to pass everything)
75
+ - `npm run test:e2e:all` runs the whole suite on Chromium, Firefox and WebKit
76
+ (`E2E_ALL_BROWSERS=1`). Chromium-only stays the default, so the main CI job is
77
+ unaffected; a separate, currently non-blocking CI job runs the matrix
78
+ - A typed OpenLayers surface: all OL types (`Map`, `View`, `Layer`,
79
+ `Source`, ...) plus the StoryMapJS extension types are re-exported, so a
80
+ consumer can build and type its own layers without depending on `ol`
81
+ separately. `storymap.map` is the raw `ol/Map` and is now honestly nullable
82
+ (`OlMap | null`) instead of an `{} as Map` placeholder
83
+ - Accessors for everything the viewer kept private:
84
+ `getBaseLayer()`, `getOverlayLayers()`/`getOverlayLayer(i)`,
85
+ `getOverlayCount()`, `setOverlayVisible()`/`setOverlayOpacity()`,
86
+ `getMinimap()`, `getLine()`/`getLineActive()`, `getMarker(n)`/`getMarkers()`
87
+ and `setExtraAttributions()`; underscore internals are no longer needed
88
+ - `tile_source_factory` may return a full `ol/layer/Layer`, not only a source,
89
+ so a custom layer can carry its own opacity, z-index and events. A layer
90
+ without a source (Allmaps' `WarpedMapLayer`) passes through untouched —
91
+ the engine fields are `Layer`-typed and source reads go through a
92
+ capability check instead of assuming a tile source
93
+ - `imageready` event (`{ source, kind, layer }`, now a typed
94
+ `ImagereadyPayload` export with `kind: "iiif" | "zoomify" | "tiles"`)
95
+ fired once an image source is actually ready, and re-fired on the
96
+ storymap: `loaded` can fire before the imagery exists. The zoomify base
97
+ layer never announced itself — only its minimap did — so a host waiting
98
+ on the event hung on legacy stories; it fires now
99
+ - `storymap.dispose()` releases timers, the resize observer, window/document
100
+ listeners, running slide animations, the slider and the OpenLayers map
101
+ - `isImageSpace()` tells an IIIF image presented as a picture of the world
102
+ (`map_as_image`) from a georeferenced IIIF map; the five places that tested
103
+ `map_type === "iiif" && map_as_image` inline now share it
104
+ - The no-op `show()`/`hide()` methods (map and marker) are marked deprecated
105
+ with the reason, and the surviving map/marker methods are documented as
106
+ aliases over the OpenLayers map
107
+ - `marker.createPopup()` is back as a deprecated no-op, so pre-0.10 code that
108
+ calls it keeps working. It never did anything upstream either: the base
109
+ `MapMarker._createPopup` had an empty body and the Leaflet override's body
110
+ was commented out, so the `map_popup` option that called it never had an
111
+ effect
112
+ - `map.addTo(container)` / `map.removeFrom(container)` keep their original
113
+ `DomMixed` behaviour (append/remove the map container, fire
114
+ `added`/`removed`) and are now OpenLayers-aware: `addTo` re-attaches the map
115
+ target and calls `updateSize()` after the move, `removeFrom` untargets the
116
+ map so it does not render into a detached node
117
+
118
+ Fixed
119
+ -----
120
+ - A IIIF `requiredStatement`'s `label` was discarded, so a manifest that labels
121
+ its statement — "Credit", "Rights holder", "Photographer" — showed the bare
122
+ value. The label is now kept ("Attribution: …") where there is one, and an
123
+ unlabelled statement is still the bare value, unchanged
124
+ - An IIIF `Collection` was accepted as a Manifest and its member Manifests were
125
+ read as if they were Canvases, producing text-only slides with no media, no
126
+ locations and no warning. A Collection is now detected and reported by name
127
+ with its members instead
128
+ - A IIIF manifest's canonical ids were dropped, so a stop could not be
129
+ addressed by its own id even though the viewer already resolves deep links by
130
+ `uniqueid`. Canvas `id` (falling back to the Manifest's) now lands on the
131
+ slide, and an annotation-driven stop gets `<canvasId>#<index>` so it is
132
+ addressable without colliding with the canvas it annotates
133
+ - A slide with body text and no headline rendered a literal "headline" as an
134
+ `<h2>`: `Text`'s constructor seeded its data with the placeholder strings
135
+ "headline"/"text", which `mergeData` only overwrites when the key is
136
+ present. The empty strings its render guards already expect
137
+ - `e2e/known-issues/issue-288` tested neither half of what it claimed: without
138
+ `hasTouch` the browser still reports `pointer: fine`, so `Browser.touch` and
139
+ `Browser.mobile` were false and the desktop branch rendered, and the click
140
+ landed on `.vco-slidenav-next`, which is `display: none` on mobile. It now
141
+ enables touch, asserts the mobile branch is the one under test, checks the
142
+ `touch-action: pan-y` rule the fix is actually about, and drives a real
143
+ touch drag (via CDP) to show a vertical swipe scrolls the page past the
144
+ storymap
145
+ - `e2e/known-issues/issue-452` reported a `zoom` declaration that exists in no
146
+ stylesheet. OpenLayers ships `.ol-viewport canvas { all: unset }`, and Firefox
147
+ and WebKit enumerate `zoom` as a *declared* property once `all` has reset it
148
+ while Chromium does not. It now asserts against the stylesheet's source text
149
+ - The touch-scrollbar assertion in `e2e/scroll-hint` compared
150
+ `getComputedStyle().scrollbarWidth` against `"thin"`/`"auto"`, which is not
151
+ comparable across engines: Chromium computes `auto`, Firefox computes `none`
152
+ for the same declaration. The declaration is now checked in the stylesheet
153
+ source, and the runtime half is skipped where Playwright does not report
154
+ touch (WebKit)
155
+ - A new georeferenced-IIIF fixture (`issue-iiif-geo`), because the negative
156
+ `isImageSpace()` case could not be reached from the existing ones: the
157
+ document sets `map_as_image`, and the document wins over a constructor option
158
+ - The consent registry keyed its stored decisions on a *localized* label, so
159
+ the same service hashed differently in German than in English and renaming a
160
+ label orphaned every saved decision. Keys are now stable and namespaced
161
+ (`map:tiles`, `fonts:web`, `media:<type>`) with the localized name carried
162
+ alongside, and existing decisions are migrated on read. The per-slide dialog
163
+ also asked "Load content from youtube?" — it now shows the media's display
164
+ name, matching the start-of-story dialog
165
+ - 27 of the 29 bundled locales had no `consent_*` strings at all and silently
166
+ fell back to English, including the whole start-of-story dialog. The 9
167
+ missing keys are translated in 23 locales; `npm run check:locales` now fails
168
+ on a new gap (its `--strict` flag was documented but never implemented, and
169
+ the check was not in CI) instead of only reporting
170
+ - Removing a map marker did not renumber the ones behind it, even though
171
+ `marker_number` is the index a click hands to `goTo()`: a click on the third
172
+ pin after removing the second navigated to the wrong slide
173
+ - Every slide got an empty element id. The generated `uniqueid` was only
174
+ created when the field was the empty string, but it is optional in the
175
+ schema and absent from 47 of the 48 bundled fixtures
176
+ - `dispose()` released the timers and the OpenLayers map but nothing they
177
+ owned, so a torn-down storymap left its slider, slides, media players,
178
+ markers and buttons in the document. Each class now releases what it owns,
179
+ and three listeners that could not be removed at all (registered as inline
180
+ arrows or a throwaway `.bind()`) keep a reference
181
+ - A preload was tracked in one `preloadTimer` that held either a
182
+ `setTimeout` or a `requestIdleCallback` handle. Both are numbers, so
183
+ cancelling one with the other's API appeared to work while leaking it
184
+ - map_bbox was ignored for every IIIF map: the runtime test was "map_type is
185
+ iiif", so a *georeferenced* IIIF map was treated as image space and its view
186
+ was fitted to the image extent instead of the bbox
187
+ - 12 tile/vector source sites declared `attributions: []`, so the OSM, Stadia,
188
+ Mapbox, Esri, Carto, OpenTopo, Esri Ocean, NASA, overlay and mini-map
189
+ credits never reached the attribution control. They are now credited from
190
+ the source; custom `.vco-map-attribution` lines are unchanged
191
+ - Navigating mutated the caller's document: the computed marker zoom was
192
+ written back onto `slides[i].location.zoom`, and `StoryMap.data` is that very
193
+ object. The zoom ladder now lives in an internal store; the authored value is
194
+ left alone and is still used for the min/max bounds
195
+ - `map_options.interactions` was documented as replacing the defaults; it is
196
+ additive (the viewer's own pan/zoom set is always installed)
197
+ - Image media never called onLoaded(): the call had drifted into a dead
198
+ position after a `return` in _altText(), so every image slide kept a
199
+ permanent "Loading Image" overlay painted over it and never rendered its
200
+ credit or caption
201
+ - Consent-denied media threw a TypeError on desktop: updateMediaDisplay()
202
+ dereferenced `content_item.style` on the empty placeholder
203
+ - Map.goTo() fired its change event twice for a slide with no location
204
+ - start_at_slide supplied by the storymap *data* was ignored: the field was
205
+ read before the data merge and the slider's opening goTo() fires before the
206
+ change listener is attached
207
+ - The menubar collapse toggle was a no-op: the portrait branch it only
208
+ appears in unconditionally overwrote the map height it asked for
209
+ - map_type "stadia" with no style resolved to a non-Stadia style name, so
210
+ every tile 404'd; setMapOption("map_bbox") rebuilt the View without the
211
+ deliberate constraints
212
+ - The start-of-story consent dialog listed services the visitor had already
213
+ answered, and left answered rows greyed out rather than removing them
214
+ (two consent e2e tests were failing because of this)
215
+ - The YouTube IFrame API poll retried forever; Vimeo's embed URL used &amp;
216
+ separators that are not decoded in a URL property; the horizontal swipe
217
+ constraint clamp was inverted; slide positions were computed from the
218
+ previous width; goToId() with an unknown id jumped to slide 0
219
+ - 7 of the 18 media types had no icon glyph, so their error boxes were blank
220
+ - he.json carried a UTF-8 BOM that made it unparseable by standard JSON tools
221
+
222
+ Security
223
+ --------
224
+ - The slide-text sanitizer was a denylist that copied every attribute
225
+ verbatim. `style` came through untouched, which allowed a pasted
226
+ full-viewport opaque overlay over the map and controls (chrome spoofing and
227
+ clickjacking from one attribute). It is now an allowlist; `target` is always
228
+ forced to `_blank`, `id`/`name` are dropped, `srcset` is validated per
229
+ candidate, and rebuilt embeds are sandboxed with a no-referrer policy
230
+ - Seven innerHTML sinks that bypassed the sanitizer are routed through it:
231
+ media credit, media caption, the navigation headline, the call-to-action
232
+ text, the Juxtapose iframe, and the map attribution line
233
+ - media and image link hrefs are protocol-checked, so a `javascript:` href in
234
+ the storymap JSON is no longer a click-through XSS
235
+ - a crafted `stock:` font name resolved to an arbitrary same-origin file
236
+ - the schema validator did not implement `anyOf`, so map_bbox,
237
+ map_overview_center and the zoomify block were accepted completely
238
+ unvalidated; `format` and `maxLength` are now honoured
239
+
240
+ Removed
241
+ -------
242
+ - The inert option keys `less_bounce`, `map_subdomains`, `map_popup`,
243
+ `zoom_distance`, `dragging` and `path_gfx`: documented and accepted, but read
244
+ by nothing. They are gone from the schema, the types and the defaults, and
245
+ documents carrying them still validate, because the schema does not close
246
+ `additionalProperties`
247
+
248
+ Changed
249
+ -------
250
+ - The map engine is genuinely optional. `StoryMap._map` is `null` rather than a
251
+ `{}` stub, so the accessors' `this._map ? … : neutral` guards mean what they
252
+ say instead of passing on a truthy object and then calling a method on it,
253
+ and the paths that only make sense with a map now throw a named error if they
254
+ are reached without one
255
+ - `StoryMap._el.map` is `HTMLElement | null` rather than `HTMLElement`
256
+ - A second viewer on a page asking for a different `language` now **throws**
257
+ instead of silently repainting the first one. The UI strings are a single
258
+ page-wide binding read while a viewer is constructed, so a conflict was
259
+ never survivable; the claim is released by `dispose()`. Only an explicit
260
+ `language` — the constructor option or the document's — counts as a request:
261
+ a viewer that was not given one adopts the page's current locale, so calling
262
+ the public `setLanguage()` and then building viewers without a `language`
263
+ option keeps the locale instead of resetting the page to English. The
264
+ trade-off is that such a viewer follows a previous viewer's
265
+ `refreshLanguage()`
266
+ - Several viewers on a page no longer overwrite each other's consent
267
+ decisions: each manager merges into the shared record and re-reads it on
268
+ every ask, instead of writing its whole set back
269
+ - With `keyboard: true` on more than one viewer, an arrow keypress goes to the
270
+ viewer that holds focus, or else the one interacted with most recently
271
+ - External scripts and stylesheets are injected once per URL for the page, so
272
+ two viewers no longer both load the YouTube/SoundCloud APIs and the font
273
+ theme
274
+ - `dispose()` empties the host container and turns the public methods and
275
+ accessors into no-ops; there is no re-init path (build a new StoryMap)
276
+ - strictNullChecks is enabled. The `{} as HTMLElement` placeholders it was
277
+ masking are now honestly nullable, which is what the consent-denied crash
278
+ came from
279
+ - morpheus (an inlined UMD build that shipped no types) is replaced by a
280
+ ~130 line Web Animations API wrapper with the same call signature: one
281
+ dependency and one hand-maintained .d.ts removed, -5 kB raw and no
282
+ measurable change over the wire. morpheus gzipped well, so most of the raw
283
+ saving is offset by the new code; the win here is the dependency and the
284
+ type stub, not the bytes
285
+ - npm run check:locales reports which locales are missing which strings.
286
+ 28 of 29 are missing 8-10, mostly the per-service consent labels
287
+ - Docs corrected: DEVELOPMENT.md described a CommonJS/UMD build with a
288
+ KLStoryMap global (it is ESM-only), the CHANGELOG claimed consent labels
289
+ were fully translated and that zoomify was removed (both false), and
290
+ README/index.html said slide text is rendered raw (it is sanitized)
291
+
292
+ 0.10.0 - 0.10.7 (2026-09-22 to 2026-09-25)
293
+ ------------------------
294
+ Released as eight patches without individual changelog entries; this is the
295
+ consolidated list. Viewer-only restructure of the repository:
4
296
  - Removed the editor Flask backend, CDN staging and all legacy build artifacts
5
297
  - Replaced webpack with Vite (dev/build/preview), default Vite project layout
6
298
  - Converted the source to strict TypeScript (target ES2022, noImplicitAny, no explicit any)
7
- - Replaced Leaflet with OpenLayers; IIIF Image API replaces Zoomify (breaking: map_type "zoomify" is gone, use "iiif")
299
+ - Replaced Leaflet with OpenLayers. IIIF Image API ("map_type": "iiif") is the
300
+ recommended image basemap; the legacy Zoomify pyramid ("map_type": "zoomify")
301
+ is retained as a deprecated basemap and warns when it loads
8
302
  - Converted Less to SASS with zero deprecation warnings (@use only, no @import, no vendor prefixes, no postcss-scss)
9
303
  - Fonts bundled via @fontsource + @fontsource-utils/scss mixins (woff2, latin subsets); no runtime font CDN requests
10
304
  - New exchange format: IIIF Presentation API 3.0 manifests (docs/storymap-as-iiif-manifest.md) with navPlace geo +
@@ -16,6 +310,67 @@ Viewer-only restructure of the repository:
16
310
  - Dropped code for pre-2022 browsers: XHR -> fetch, removed vendor detection, engine workarounds, pollers,
17
311
  minEmoji sprite polyfill and Knight Lab tracking
18
312
  - Bug fixes: null-offset crashes, IIIF source races, unique-id generation, swipe direction check, empty-block cleanup
313
+ - Stacked raster overlays with per-layer presentation (opacity, visibility,
314
+ attribution, className, blendMode, lon/lat extent), runtime setters and
315
+ setMapOption rebuild; minimap overview constraint via overview_extent
316
+ - Slide transition events (transitionstart/transitionend), guaranteed goTo
317
+ change events, opt-in global keyboard navigation
318
+ - Runtime language switching without reload (MenuBar.refreshLabels,
319
+ StoryMap.refreshLanguage); locale fallback no longer mutates English;
320
+ German fullscreen labels
321
+ - Attribution refresh on basemap switch (+setExtraAttributions); identical
322
+ credits collapse to one entry; route lines pinned above rebuilt tile
323
+ layers; font_css resolves page-relative; slide colors accept any CSS color
324
+ - Consent: decisions persist in localStorage (storymapjs-consent, no expiry)
325
+ instead of a 90-day cookie; a start-of-story dialog lists the external
326
+ services the story uses (map tiles, media services, external fonts) and
327
+ offers allow all, decline all or a decision per service, with per-service
328
+ panels as the fallback for services discovered later. Only en.json
329
+ translates every label: the other 28 bundled locales are each missing the
330
+ per-service consent strings and fall back to English (npm run check:locales)
331
+ - Mobile gestures: iOS swipe navigation fixed — signed gesture deltas (a
332
+ rightward swipe on the left half no longer counts as "next"), touchcancel
333
+ handled without leaking touchmove/mouseleave listeners (swipes used to stop
334
+ working after the first slide), touchend reads changedTouches, and
335
+ touch-action: pan-y on the slider keeps vertical page scrolling
336
+ - Accessibility: image alt text end-to-end (schema, IIIF storymap:mediaAlt,
337
+ caption-as-plain-text fallback), aria-live slide announcements, real <button>
338
+ menubar actions with :focus-visible styling, keyboard-operable slider nav
339
+ arrows (role/tabindex/Enter/Space), prefers-reduced-motion honored
340
+ (instant slide changes, no autoplay), embed page allows pinch-zoom
341
+ - Image performance: offscreen slide images are lazy-loaded and
342
+ async-decoded (upgraded to eager when their slide becomes active), IIIF
343
+ image URLs request container-matched widths, optional srcset/sizes pass
344
+ through for plain images
345
+ - Fonts: non-latin subsets (cyrillic, greek, hebrew, vietnamese) shipped
346
+ from the installed Fontsource packages where a family provides them, plus a
347
+ new stock:cairo theme with arabic coverage
348
+ - IIIF: per-slide image regions (location.region as IIIF xywh in image
349
+ pixels) fit the view on navigation for image-map stories, encoded in
350
+ manifests as storymap:imageRegion
351
+ - Storymap JSON: schema entries for map_area, overlays (with per-layer
352
+ opacity, visibility, attribution, className, blendMode and lon/lat extent),
353
+ overview_extent and keyboard — plus the slide fields location.region and
354
+ media.alt/srcset/sizes, and a fix for overlays and overview_extent being
355
+ silently dropped when they came from the data file instead of the options
356
+ - IIIF manifests: the same options as storymap:mapArea, storymap:overlays,
357
+ storymap:overviewExtent and storymap:keyboard terms on the map
358
+ configuration service, storymap:mediaSrcset / storymap:mediaSizes on the
359
+ canvas, and the native geospatial vocabulary where IIIF has it — a navPlace
360
+ Polygon as the story extent (map_bbox), an IIIF Image API Selector as
361
+ location.region
362
+ - IIIF manifests: storymap:georeferencedLayers places a IIIF image on the
363
+ geographic map from a Georeference Extension annotation body (affine
364
+ placement of its ground control points); placements needing a
365
+ non-affine transform or a rotated sheet are reported and skipped, so
366
+ warped layers stay a tile_source_factory/Allmaps concern
367
+ - Map providers: tile_source_factory option injects custom OpenLayers tile
368
+ layers/sources (e.g. WMS) for the base map, overlays and minimap, with
369
+ recipes in the migration guide
370
+ - Embed: &autoplay=<ms> URL parameter for automatic slide playback
371
+ - Upstream audit: docs/KNOWN_ISSUES.md reconciled with the implementation
372
+ (60 of 109 triaged issues verified fixed, one-by-one verdicts and
373
+ regression specs for each)
19
374
 
20
375
  0.9.5 (2025-11-05)
21
376
  * Implement basic Audio and Video media types
@@ -106,16 +461,3 @@ Viewer-only restructure of the repository:
106
461
  * PR #302 Media fixes including pause of video types when navigating away from slide
107
462
  * PR #303 Adds custom map marker upload in editor
108
463
  * PR #312 Adds Greek translation to StoryMap editor
109
-
110
- ## 1.0.0 (unreleased)
111
-
112
- Viewer-only restructure of the repository:
113
- - Removed the editor Flask backend, staging and legacy build artifacts
114
- - Replaced webpack with Vite (dev/build/preview), default project layout
115
- - Converted the source to strict TypeScript (target ES2022)
116
- - Replaced Leaflet with OpenLayers; IIIF Image API replaces Zoomify (breaking)
117
- - Converted Less to SASS; fonts bundled from npm (@fontsource) instead of runtime CDN requests
118
- - Added a JSON Schema for storymap data, runtime validation with console reporting, and a CLI validator
119
- - Added ESLint + Stylelint and GitHub Actions for linting/tests and release packaging
120
- - Playwright e2e suite over all examples, Vitest for units
121
- - Dropped code paths for pre-2022 browsers (legacy vendor prefixes, IE/old-engine fallbacks)
package/README.md CHANGED
@@ -10,7 +10,9 @@ This fork is a **viewer-only library**: it renders existing StoryMap JSON
10
10
  files (or IIIF Presentation manifests) with TypeScript + Vite + OpenLayers.
11
11
  There is no authoring tool — create your storymap JSON by hand or with your
12
12
  own code, and see `docs/` for the migration notes from the original
13
- Knight Lab release.
13
+ Knight Lab release. The library also exports `storymapToManifest()`, which
14
+ produces a IIIF manifest from a storymap document (`npm run convert:iiif`
15
+ does the same from the command line; see `docs/storymap-as-iiif-manifest.md`).
14
16
 
15
17
  ## Development
16
18
 
@@ -40,6 +42,14 @@ Points are set to only display on mouseover in image mode, but you can set map_a
40
42
  To disable connecting lines on maps set `map_as_image: true` in the storymap
41
43
  options (the default `false` renders cartography).
42
44
 
45
+ `storymap.map` is the raw OpenLayers map, typed with the re-exported `ol`
46
+ types, and `getBaseLayer()`, `getOverlayLayers()`, `getMinimap()`,
47
+ `getMarkers()` and friends hand out the layers the viewer built. Listen for
48
+ `imageready` to run code against the real imagery, and call
49
+ `storymap.dispose()` when the embedding view goes away — see
50
+ [docs/migration-from-knightlab.md](docs/migration-from-knightlab.md#reaching-the-map-layers-and-markers)
51
+ for the full surface.
52
+
43
53
  The menubar buttons can be disabled individually:
44
54
 
45
55
  show_overview: false, // map overview button
@@ -92,7 +102,8 @@ an opaque slide panel instead of the gradient over the map), set
92
102
 
93
103
  Any value containing `{z}` renders as a raster XYZ layer; a path without `{z}`
94
104
  that looks like a URL/path renders as a vector style layer; anything else falls
95
- back to classic OSM raster.
105
+ back to classic OSM raster — except `"none"`, which builds no map at all and
106
+ runs the story as text and media only.
96
107
 
97
108
  ### Switching the basemap at runtime
98
109
 
@@ -123,14 +134,22 @@ images, lists, emphasis and spans in your slides, e.g.:
123
134
 
124
135
  The `vco-note` span renders as a small grey note, like the built-in credits.
125
136
 
126
- **Caution:** the text is rendered raw — it is not sanitized. Only load
127
- storymaps from sources you trust.
137
+ **Caution:** the text is sanitized, but sanitizing is a mitigation rather
138
+ than a guarantee. Prose and media formatting survive (`class`, `alt`, `width`,
139
+ table attributes, and so on), scripts and other executable tags are dropped
140
+ with their contents, event-handler attributes are stripped, every URL
141
+ attribute is checked to be `http(s)`, and `<iframe>` embeds are rebuilt into
142
+ a sandboxed, `no-referrer` element. `style`, `id` and `name` are _not_ allowed,
143
+ and a link's `target` is always forced to `_blank`. The same sanitizer covers
144
+ media credit, media caption, the navigation headline and the map attribution
145
+ line. Still: only load storymaps from sources you trust.
128
146
 
129
147
  ## GDPR consent for external services
130
148
 
131
149
  Set the `consent_required` option to `true` to ask for permission before
132
150
  anything is loaded from external services (media embeds such as YouTube,
133
- Twitter or SoundCloud, map tiles, and external font CSS):
151
+ Twitter or SoundCloud, slide narration audio, map tiles, and external font
152
+ CSS):
134
153
 
135
154
  {
136
155
  "consent_required": true,
@@ -138,11 +157,26 @@ Twitter or SoundCloud, map tiles, and external font CSS):
138
157
  }
139
158
 
140
159
  Each service asks with an Allow/Deny panel; answering one panel resolves every
141
- pending panel of the same service. If a decision was already stored in the
142
- cookie, the panel is skipped entirely. Denied services show a placeholder
160
+ pending panel of the same service. Denied services show a placeholder
143
161
  instead of the media, and the map renders without tiles until they are
144
- allowed. Decisions are stored in a cookie (`storymapjs-consent`) for 90
145
- days — clearing cookies asks again.
162
+ allowed.
163
+
164
+ Before the story loads, one dialog lists every external service it uses (map
165
+ tiles, media services including slide narration, external fonts) with three
166
+ choices: **Allow all**, **Decline all**, or a decision per service. A story
167
+ with no map (`map_type: "none"`) has no tile row to answer. The dialog is
168
+ skipped once every service has a stored decision; per-service panels still
169
+ appear for services discovered later (e.g. a preloaded slide).
170
+
171
+ Decisions are stored in `localStorage` under `storymapjs-consent` and have no
172
+ expiry — clearing site data asks again.
173
+
174
+ The consent labels are **not** fully translated. `src/language/locale/en.json`
175
+ defines every string; 28 bundled locales fall back to English for the keys
176
+ they lack — most are missing one, a handful are missing around ten (the
177
+ per-service consent prompts and the fullscreen button labels). Run
178
+ `npm run check:locales` to see the current state — it reports the gap per
179
+ locale and is expected to be runnable without failing.
146
180
 
147
181
  ## Troubleshooting
148
182
 
@@ -0,0 +1 @@
1
+ import"./modulepreload-polyfill-P2Xu9kJm.js";import{t as e}from"./main-DXalctuR.js";function t(e){document.title=`StoryMapJS: `+e.title}window.storymap=new e(`storymap-embed`,`./demo.json`,{},{title:t});
@@ -0,0 +1 @@
1
+ import"./modulepreload-polyfill-P2Xu9kJm.js";import{t as e}from"./main-DXalctuR.js";import{n as t,t as n}from"./harness-support-Do7sIp2j.js";window.__smErrors=[],window.__smReady=!1,window.addEventListener(`error`,e=>{window.__smErrors.push(String(e.message||e))});var r=new URLSearchParams(window.location.search),i=r.get(`manifest`),a=r.get(`url`),o=i===null?r.get(`example`):i,s=i===null?`/examples/`:`/examples-iiif/`,c={};if(r.get(`options`))try{c=JSON.parse(r.get(`options`))}catch(e){window.__smErrors.push(`harness: bad options param: `+e)}var l=t(window);l&&(c.tile_source_factory=l);var u=a??s+o+`.json`;fetch(u).then(e=>e.json()).then(t=>{let i=new e(`storymap-embed`,t,c,{});window.__sm=i,n(i,r.get(`record`),window),window.__smReady=!0}).catch(e=>{window.__smErrors.push(`harness: `+(e&&e.message?e.message:String(e))),window.__smReady=!0});
@@ -0,0 +1 @@
1
+ import"./modulepreload-polyfill-P2Xu9kJm.js";import{t as e}from"./main-DXalctuR.js";import{n as t,t as n}from"./harness-support-Do7sIp2j.js";window.__smErrors=[],window.__smReady=!1,window.addEventListener(`error`,e=>{window.__smErrors.push(String(e.message||e))});var r=new URLSearchParams(window.location.search),i={a:r.get(`a`)??`katrina`,b:r.get(`b`)??`seurat`},a={a:o(r.get(`aopts`)),b:o(r.get(`bopts`))};for(let[e,n]of Object.entries(a)){let r=t(window);r&&(n.tile_source_factory=r),a[e]=n}function o(e){if(!e)return{};try{return JSON.parse(e)}catch(e){return window.__smErrors.push(`harness-multi: bad options: `+e),{}}}async function s(e){let t=await fetch(`/examples/`+i[e]+`.json`);if(!t.ok)throw Error(`no example `+i[e]);return t.json()}var c=r.get(`shared`)===`1`?await s(`a`):null;try{let t=c??await s(`a`);window.__smA=new e(`sm-a`,t,a.a,{}),n(window.__smA,r.get(`record`),window,`A`);let i=c??await s(`b`);window.__smB=new e(`sm-b`,i,a.b,{}),n(window.__smB,r.get(`record`),window,`B`)}catch(e){window.__smErrors.push(`harness-multi: `+(e?.message??e))}window.__smReady=!0;
@@ -0,0 +1 @@
1
+ function e(e,t,r,i=``){let a=(t??``).split(`,`).map(e=>e.trim()).filter(Boolean);if(a.length!==0){r.__events=r.__events??[];for(let t of a)e.on(t,e=>{r.__events.push({type:t,viewer:i,payload:n(e)})})}}function t(e){return typeof e.__tileSourceFactory==`function`?e.__tileSourceFactory:void 0}function n(e){if(typeof e!=`object`||!e)return e;let t={};for(let[a,o]of Object.entries(e))if(typeof o!=`object`||!o)t[a]=typeof o==`function`?`[fn]`:o;else if(a===`source`||a===`layer`)t[a]={type:o.constructor?.name??null,state:typeof o.getState==`function`?o.getState():void 0,url:o.url_??o.href_??r(o,`url`)};else if(a===`target`)t[a]=i(o);else if(Array.isArray(o))t[a]=o.map(e=>n(e));else{let e=Object.getPrototypeOf(o);t[a]=e===Object.prototype||e===null?n(o):{type:o.constructor?.name??null}}return t}function r(e,t){try{return e.get?.(t)}catch{return}}function i(e){let t=a(e)?e:a(e?._map)?e._map:null;if(!t)return{type:e?.constructor?.name??null};let n=t.getView(),r=t.getSize();return{type:e?.constructor?.name??null,size:r?[r[0],r[1]]:null,center:n?.getCenter?.()??null,resolution:n?.getResolution?.()??null,projection:n?.getProjection?.()?.getCode?.()??null}}function a(e){return!!e&&typeof e.getSize==`function`&&typeof e.getView==`function`}export{t as n,e as t};
@@ -0,0 +1 @@
1
+ import"./modulepreload-polyfill-P2Xu9kJm.js";var e=[{id:`katrina`,title:`Hurricane Katrina`,kind:`Map`},{id:`population`,title:`US Population Shifts`,kind:`Map`},{id:`marktwain`,title:`Mark Twain's Travels`,kind:`Map`},{id:`seurat`,title:`A Sunday on La Grande Jatte`,kind:`Large image (legacy)`},{id:`iiif-wellcome`,title:`Wellcome Collection (IIIF)`,kind:`IIIF`},{id:`president`,title:`A Month in the Life of President Obama`,kind:`Map`},{url:`https://s3.amazonaws.com/uploads.knightlab.com/storymapjs/a1a349b51799ee49e96bed10cc235e7f/garden-of-earthly-delights/published.json`,thumb:`bosch-garden`,title:`The Garden of Earthly Delights – Hieronymus Bosch`,kind:`Knight Lab example`},{url:`https://uploads.knightlab.com/storymapjs/3df56e350378e51781746bfb2a2ea428/test/published.json`,thumb:`southern-literary-trail`,title:`Southern Literary Trail`,kind:`Georgia Humanities`}];function t(e){let t=e.url??`examples/`+e.id+`.json`,n=e.thumb??e.id??``,r=document.createElement(`a`);r.className=`card`,r.href=`./embed/index.html?url=${encodeURIComponent(t)}`;let i=document.createElement(`span`);i.className=`header-image`;let a=document.createElement(`span`);a.className=`header-image-background bw`,a.style.backgroundImage=`url('./thumbs/${n}.jpg'), linear-gradient(135deg, #b8b8b8, #646464)`,a.setAttribute(`role`,`img`),a.setAttribute(`aria-label`,e.title),i.append(a);let o=document.createElement(`article`);o.className=`card-content`;let s=document.createElement(`h3`);s.textContent=e.title,o.append(s);let c=document.createElement(`footer`);return c.textContent=e.kind,r.append(i,o,c),r}var n=document.getElementById(`examples-cards`);if(n){n.classList.add(`cards-link`);for(let r of e)n.append(t(r))}var r=document.getElementById(`demo-frame`);if(r){let e=()=>{r.style.height=window.innerHeight-20+`px`};e(),window.addEventListener(`resize`,e)}