@projektemacher/storymapjs 0.10.7 → 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 (532) hide show
  1. package/CHANGELOG +350 -19
  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 +84 -0
  253. package/dist/css/fonts/font.opensans-gentiumbook.css +183 -0
  254. package/dist/css/fonts/font.playfair-faunaone.css +39 -0
  255. package/dist/css/fonts/font.playfair.css +147 -0
  256. package/dist/css/fonts/font.pt.css +183 -0
  257. package/dist/css/fonts/font.roboto-megrim.css +3 -0
  258. package/dist/css/fonts/font.rufina-sintony.css +3 -0
  259. package/dist/css/fonts/font.ubuntu.css +291 -0
  260. package/dist/css/fonts/font.unicaone-vollkorn.css +84 -0
  261. package/dist/css/storymap.css +1 -1
  262. package/dist/demo.html +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 +313 -11
  338. package/dist/docs/readme.html +40 -9
  339. package/dist/embed/index.html +1 -1
  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 +16 -10
  405. package/dist/js/storymap.d.ts +1439 -114
  406. package/dist/js/storymap.js +24654 -21936
  407. package/dist/js/storymap.js.map +1 -1
  408. package/dist/navplace-properties.json +40 -0
  409. package/docs/migration-from-knightlab.md +229 -9
  410. package/docs/storymap-as-iiif-manifest.md +559 -135
  411. package/package.json +11 -8
  412. package/schema/storymap.schema.json +431 -78
  413. package/src/animation/easings.ts +8 -1
  414. package/src/animation/tween.ts +186 -0
  415. package/src/core/Browser.ts +6 -5
  416. package/src/core/Load.ts +54 -2
  417. package/src/core/Util.ts +255 -193
  418. package/src/core/mixins.ts +24 -7
  419. package/src/core/viewers.ts +94 -0
  420. package/src/dom/DomEvent.ts +27 -8
  421. package/src/globals.d.ts +8 -0
  422. package/src/language/Language.ts +199 -25
  423. package/src/language/locale/.expected-gaps.json +86 -0
  424. package/src/language/locale/be.json +15 -2
  425. package/src/language/locale/bg.json +15 -2
  426. package/src/language/locale/cs.json +15 -2
  427. package/src/language/locale/de.json +12 -1
  428. package/src/language/locale/el.json +15 -2
  429. package/src/language/locale/en.json +6 -2
  430. package/src/language/locale/es.json +15 -2
  431. package/src/language/locale/et.json +5 -1
  432. package/src/language/locale/fr.json +15 -2
  433. package/src/language/locale/he.json +16 -3
  434. package/src/language/locale/hu.json +15 -2
  435. package/src/language/locale/is.json +5 -1
  436. package/src/language/locale/it.json +15 -2
  437. package/src/language/locale/jp.json +15 -2
  438. package/src/language/locale/ko.json +15 -2
  439. package/src/language/locale/nl.json +15 -2
  440. package/src/language/locale/nn.json +5 -1
  441. package/src/language/locale/no.json +15 -2
  442. package/src/language/locale/pl.json +15 -2
  443. package/src/language/locale/pt.json +15 -2
  444. package/src/language/locale/ru.json +15 -2
  445. package/src/language/locale/sk.json +15 -2
  446. package/src/language/locale/sr.json +5 -1
  447. package/src/language/locale/sv.json +15 -2
  448. package/src/language/locale/tr.json +15 -2
  449. package/src/language/locale/uk.json +15 -2
  450. package/src/language/locale/ur.json +5 -1
  451. package/src/language/locale/zh-cn.json +15 -2
  452. package/src/language/locale/zh-tw.json +15 -2
  453. package/src/main.ts +92 -0
  454. package/src/map/Map.ts +183 -106
  455. package/src/map/MapMarker.ts +28 -5
  456. package/src/map/georeference.ts +325 -0
  457. package/src/map/openlayers/Map.OpenLayers.ts +850 -237
  458. package/src/map/openlayers/MapMarker.OpenLayers.ts +248 -24
  459. package/src/map/openlayers/zoomifyTiles.ts +1 -4
  460. package/src/media/EmbedUtil.ts +308 -24
  461. package/src/media/Media.ts +243 -55
  462. package/src/media/embedId.ts +104 -0
  463. package/src/media/types/Audio.ts +9 -82
  464. package/src/media/types/Blockquote.ts +2 -3
  465. package/src/media/types/DailyMotion.ts +5 -10
  466. package/src/media/types/DocumentCloud.ts +6 -35
  467. package/src/media/types/Facebook.ts +3 -4
  468. package/src/media/types/Flickr.ts +9 -9
  469. package/src/media/types/GoogleDoc.ts +3 -4
  470. package/src/media/types/HtmlMedia.ts +167 -0
  471. package/src/media/types/IFrame.ts +3 -4
  472. package/src/media/types/Image.ts +72 -6
  473. package/src/media/types/Juxtapose.ts +14 -5
  474. package/src/media/types/SoundCloud.ts +28 -6
  475. package/src/media/types/Text.ts +19 -13
  476. package/src/media/types/Twitter.ts +27 -14
  477. package/src/media/types/Video.ts +9 -79
  478. package/src/media/types/Vimeo.ts +10 -10
  479. package/src/media/types/Website.ts +23 -13
  480. package/src/media/types/Wikipedia.ts +18 -8
  481. package/src/media/types/YouTube.ts +71 -39
  482. package/src/scss/Typography.scss +1 -3
  483. package/src/scss/VCO.StoryMap.Dark.scss +18 -6
  484. package/src/scss/VCO.StoryMap.scss +37 -6
  485. package/src/scss/Variables.Dark.scss +3 -2
  486. package/src/scss/Variables.scss +3 -2
  487. package/src/scss/core/Mixins.scss +5 -63
  488. package/src/scss/fonts/font.amatic-andika.scss +3 -0
  489. package/src/scss/fonts/font.bitter-raleway.scss +6 -0
  490. package/src/scss/fonts/font.cairo.scss +79 -0
  491. package/src/scss/fonts/font.clicker-garamond.scss +5 -0
  492. package/src/scss/fonts/font.dancing-ledger.scss +1 -0
  493. package/src/scss/fonts/font.knightlab.scss +14 -0
  494. package/src/scss/fonts/font.oldstandard.scss +6 -0
  495. package/src/scss/fonts/font.opensans-gentiumbook.scss +5 -0
  496. package/src/scss/fonts/font.playfair-faunaone.scss +2 -0
  497. package/src/scss/fonts/font.playfair.scss +4 -0
  498. package/src/scss/fonts/font.pt.scss +6 -0
  499. package/src/scss/fonts/font.ubuntu.scss +4 -0
  500. package/src/scss/fonts/font.unicaone-vollkorn.scss +5 -0
  501. package/src/scss/map/VCO.MapMarker.scss +98 -3
  502. package/src/scss/media/VCO.Media.scss +7 -10
  503. package/src/scss/media/types/VCO.Media.Text.scss +8 -0
  504. package/src/scss/media/types/VCO.Media.Wikipedia.scss +2 -1
  505. package/src/scss/slider/VCO.Slide.scss +13 -3
  506. package/src/scss/slider/VCO.SlideNav.scss +11 -17
  507. package/src/scss/slider/VCO.StorySlider.scss +4 -2
  508. package/src/scss/ui/VCO.Consent.scss +44 -0
  509. package/src/scss/ui/VCO.MenuBar.Button.scss +8 -0
  510. package/src/scss/ui/VCO.Message.scss +2 -5
  511. package/src/site/site.ts +2 -1
  512. package/src/slider/Slide.ts +121 -27
  513. package/src/slider/SlideNav.ts +39 -5
  514. package/src/slider/StorySlider.ts +153 -42
  515. package/src/storymap/Consent.ts +407 -82
  516. package/src/storymap/StoryMap.ts +1192 -182
  517. package/src/storymap/content-state.ts +185 -0
  518. package/src/storymap/iiif.ts +1526 -68
  519. package/src/storymap/to-iiif.ts +921 -0
  520. package/src/storymap/validate.ts +80 -7
  521. package/src/types.ts +223 -26
  522. package/src/ui/MenuBar.ts +98 -45
  523. package/src/ui/Message.ts +9 -0
  524. package/src/ui/Swipable.ts +145 -78
  525. package/dist/assets/demo-D6cTmzn6.js +0 -1
  526. package/dist/assets/harness-BPFlzutp.js +0 -1
  527. package/dist/assets/index-DDsPBPZA.js +0 -1
  528. package/dist/assets/main-Y-MYUSJ4.js +0 -17
  529. package/src/animation/morpheus.d.ts +0 -41
  530. package/src/scss/media/types/VCO.Media.Instagram.scss +0 -7
  531. package/src/scss/media/types/VCO.Media.Profile.scss +0 -5
  532. package/src/ui/Draggable.ts +0 -374
@@ -1,7 +1,6 @@
1
+ import { dailymotionId } from "../embedId";
1
2
  import { Media } from "../Media";
2
3
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
4
- import { ratio } from "../../core/Util";
5
4
 
6
5
  /* Media.DailyMotion
7
6
  ================================================== */
@@ -13,7 +12,7 @@ export default class DailyMotion extends Media {
13
12
  ================================================== */
14
13
  _loadMedia() {
15
14
  // Loading Message
16
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
15
+ this.loadingMessage();
17
16
 
18
17
  // Create Dom element
19
18
  this._el.content_item = Dom.create(
@@ -23,13 +22,10 @@ export default class DailyMotion extends Media {
23
22
  );
24
23
 
25
24
  // Get Media ID
26
- const id = this.data.url.match("video")
27
- ? this.data.url.split("video/")[1]
28
- : this.data.url.split("embed/")[1];
29
- if (!id) {
25
+ this.media_id = dailymotionId(this._url()) ?? "";
26
+ if (!this.media_id) {
30
27
  throw new Error("Invalid DailyMotion URL");
31
28
  }
32
- this.media_id = id.split(/[?&]/)[0];
33
29
 
34
30
  // API URL
35
31
  const api_url =
@@ -47,8 +43,7 @@ export default class DailyMotion extends Media {
47
43
 
48
44
  // Update Media Display
49
45
  _updateMediaDisplay() {
50
- this._el.content_item.style.height =
51
- ratio.r16_9({ w: this._el.content_item.offsetWidth }) + "px";
46
+ this._sizeContentItemTo16x9();
52
47
  }
53
48
 
54
49
  _stopMedia() {
@@ -1,41 +1,12 @@
1
- import { Media } from "../Media";
2
- import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
4
- import { validateWebURL } from "../EmbedUtil";
1
+ import { WebsiteBase } from "./Website";
5
2
 
6
3
  /* Media.DocumentCloud
7
- Embeds a DocumentCloud document viewer (issue #437)
4
+ Embeds a DocumentCloud document viewer (issue #437) — the same iframe
5
+ embed as the website type, with its own CSS class.
8
6
  ================================================= */
9
7
 
10
- export default class DocumentCloud extends Media {
11
- /* Load the media
12
- ================================================== */
13
- _loadMedia() {
14
- // Loading Message
15
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
16
-
17
- // Create Dom element
18
- this._el.content_item = Dom.create(
19
- "div",
20
- "vco-media-item vco-media-iframe vco-media-documentcloud",
21
- this._el.content,
22
- );
23
-
24
- // the canonical document URL renders the standalone viewer; rebuilt
25
- // from a validated src to keep stored XSS out of the storymap JSON
26
- const src = validateWebURL(this.data.url);
27
- if (!src) {
28
- this.loadErrorDisplay("Invalid URL.");
29
- return;
30
- }
31
- const iframe = document.createElement("iframe");
32
- iframe.setAttribute("src", src);
33
- this._el.content_item.appendChild(iframe);
34
- this.onLoaded();
35
- }
36
-
37
- // Update Media Display
38
- _updateMediaDisplay() {
39
- this._el.content_item.style.height = this.options.height + "px";
8
+ export default class DocumentCloud extends WebsiteBase {
9
+ protected extraClass(): string {
10
+ return "vco-media-documentcloud";
40
11
  }
41
12
  }
@@ -1,6 +1,5 @@
1
1
  import { Media } from "../Media";
2
2
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
4
3
 
5
4
  /* Media.Facebook
6
5
  Embeds a Facebook post, video or reel via the plugins endpoint
@@ -12,7 +11,7 @@ export default class Facebook extends Media {
12
11
  ================================================== */
13
12
  _loadMedia() {
14
13
  // Loading Message
15
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
14
+ this.loadingMessage();
16
15
 
17
16
  // Create Dom element
18
17
  this._el.content_item = Dom.create(
@@ -21,7 +20,7 @@ export default class Facebook extends Media {
21
20
  this._el.content,
22
21
  );
23
22
 
24
- const url = this.data.url;
23
+ const url = this._url();
25
24
  const href = encodeURIComponent(url);
26
25
  const embed =
27
26
  /\/videos?\//.test(url) || /\/watch/.test(url) || /\/reel\//.test(url)
@@ -36,6 +35,6 @@ export default class Facebook extends Media {
36
35
 
37
36
  // Update Media Display
38
37
  _updateMediaDisplay() {
39
- this._el.content_item.style.height = this.options.height + "px";
38
+ this._sizeContentItemToOptionHeight();
40
39
  }
41
40
  }
@@ -1,6 +1,6 @@
1
+ import { flickrId } from "../embedId";
1
2
  import { Media } from "../Media";
2
3
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
4
4
 
5
5
  /* Media.Flickr
6
6
 
@@ -13,7 +13,7 @@ export default class Flickr extends Media {
13
13
  ================================================== */
14
14
  _loadMedia() {
15
15
  // Loading Message
16
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
16
+ this.loadingMessage();
17
17
 
18
18
  // Create Dom element
19
19
  this._el.content_item = Dom.create(
@@ -55,18 +55,18 @@ export default class Flickr extends Media {
55
55
  }
56
56
 
57
57
  establishMediaID() {
58
- const marker = "flickr.com/photos/";
59
- const idx = this.data.url.indexOf(marker);
60
- if (idx === -1) {
61
- throw "Invalid Flickr URL";
58
+ // threw a bare string (not an Error) and could assign `undefined` when
59
+ // the URL had the host but no photo segment
60
+ const id = flickrId(this._url());
61
+ if (!id) {
62
+ throw new Error("Invalid Flickr URL");
62
63
  }
63
- const pos = idx + marker.length;
64
- this.media_id = this.data.url.slice(pos).split("/")[1];
64
+ this.media_id = id;
65
65
  }
66
66
 
67
67
  createMedia(d: unknown) {
68
68
  const data = d as { sizes: { size: { label: string; source: string }[] } };
69
- const best_size = this.sizes(this.options.height);
69
+ const best_size = this.sizes(Number(this.options.height ?? 0));
70
70
  const sizes = data?.sizes?.size;
71
71
  if (!sizes || !sizes.length) {
72
72
  this.loadErrorDisplay("Photo not found or private.");
@@ -1,6 +1,5 @@
1
1
  import { Media } from "../Media";
2
2
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
4
3
  import { validateWebURL } from "../EmbedUtil";
5
4
 
6
5
  /* Media.GoogleDoc
@@ -14,7 +13,7 @@ export default class GoogleDoc extends Media {
14
13
  ================================================== */
15
14
  _loadMedia() {
16
15
  // Loading Message
17
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
16
+ this.loadingMessage();
18
17
 
19
18
  // Create Dom element
20
19
  this._el.content_item = Dom.create(
@@ -24,7 +23,7 @@ export default class GoogleDoc extends Media {
24
23
  );
25
24
 
26
25
  // Get Media ID
27
- this.media_id = this.data.url;
26
+ this.media_id = this._url();
28
27
 
29
28
  // Rebuild a clean iframe from a validated src: injecting the raw
30
29
  // URL into markup would allow stored XSS via the storymap JSON
@@ -54,6 +53,6 @@ export default class GoogleDoc extends Media {
54
53
 
55
54
  // Update Media Display
56
55
  _updateMediaDisplay() {
57
- this._el.content_item.style.height = this.options.height + "px";
56
+ this._sizeContentItemToOptionHeight();
58
57
  }
59
58
  }
@@ -0,0 +1,167 @@
1
+ import { Media } from "../Media";
2
+ import Dom from "../../dom/Dom";
3
+ import { Language } from "../../language/Language";
4
+
5
+ /* Media.HtmlMedia
6
+ Shared implementation for the <audio> and <video> types. The two differ
7
+ only in the element name, the CSS class, the fallback text and the
8
+ file extension -> MIME map, so all of that is data here.
9
+ ================================================== */
10
+
11
+ /** The element this media type plays. */
12
+ export type HtmlMediaKind = "audio" | "video";
13
+
14
+ interface HtmlMediaSpec {
15
+ /** The element to create. */
16
+ kind: HtmlMediaKind;
17
+ /** File extension (lowercase, no dot) -> MIME subtype. */
18
+ extensions: Record<string, string>;
19
+ }
20
+
21
+ const AUDIO_DEFAULT: HtmlMediaSpec = { kind: "audio", extensions: { mp3: "mpeg" } };
22
+
23
+ /** MIME subtype for a file extension, or "" when it is not recognised. */
24
+ function mimeSubtype(ext: string, spec: HtmlMediaSpec): string {
25
+ return spec.extensions[ext.toLowerCase()] ?? "";
26
+ }
27
+
28
+ /** The behaviour shared by the audio and video media types. */
29
+ export class HtmlMediaBase extends Media {
30
+ declare "player_element": HTMLMediaElement | null;
31
+ declare "_onCanPlay": (() => void) | null;
32
+ declare "_onEnded": (() => void) | null;
33
+ declare "_onSourceError": (() => void) | null;
34
+
35
+ /**
36
+ * The per-kind differences. Overridden by the Audio/Video subclasses; the
37
+ * base value is never used (an HtmlMediaBase is always subclassed).
38
+ */
39
+ protected spec(): HtmlMediaSpec {
40
+ return AUDIO_DEFAULT;
41
+ }
42
+
43
+ _loadMedia() {
44
+ const spec = this.spec();
45
+ this.loadingMessage();
46
+
47
+ const media_item = Dom.create(
48
+ spec.kind,
49
+ `vco-media-item vco-media-${spec.kind} vco-media-shadow`,
50
+ this._el.content,
51
+ ) as HTMLMediaElement;
52
+ this._el.content_item = media_item;
53
+ media_item.controls = true;
54
+
55
+ const source_item = Dom.create("source", "", media_item) as HTMLSourceElement;
56
+ this._el.source_item = source_item;
57
+
58
+ // Media Loaded Event. The references are kept so dispose() can detach
59
+ // them: an inline arrow function has no other handle.
60
+ this._onEnded = null;
61
+ this._onCanPlay = () => {
62
+ this.onLoaded();
63
+ };
64
+ media_item.addEventListener("canplay", this._onCanPlay);
65
+
66
+ // Load Error Event (the source element fires it, not the media element)
67
+ this._onSourceError = () => {
68
+ this.loadErrorDisplay(Language.messages.error + " " + this.options.media_name);
69
+ };
70
+ source_item.addEventListener("error", this._onSourceError);
71
+
72
+ const url = this._url();
73
+ source_item.src = url;
74
+ const media_type = this._getType(url, spec);
75
+ // An unrecognised extension leaves the type unset so the browser can
76
+ // work it out from the URL — setting a bare "audio/" (as this used to)
77
+ // is not a valid MIME type and makes the source fail outright.
78
+ if (media_type) {
79
+ source_item.type = media_type;
80
+ }
81
+ // Subtitles: a WebVTT track, opt-in via media.subtitles. The element
82
+ // is created before the fallback text node so the fallback stays last.
83
+ if (spec.kind === "video" || spec.kind === "audio") {
84
+ const subtitles = (this.data as { subtitles?: string | null }).subtitles;
85
+ if (typeof subtitles === "string" && subtitles !== "") {
86
+ const track = Dom.create(
87
+ "track",
88
+ "vco-media-track",
89
+ media_item,
90
+ ) as HTMLTrackElement;
91
+ track.kind = "subtitles";
92
+ track.srclang = "en";
93
+ track.label = "Subtitles";
94
+ track.src = subtitles;
95
+ track.default = true;
96
+ }
97
+ }
98
+
99
+ // append as a text node: re-serializing innerHTML would replace the
100
+ // source element and drop its error listener, leaving the loading
101
+ // message on screen forever
102
+ media_item.appendChild(
103
+ document.createTextNode(
104
+ `Your browser doesn't support HTML5 ${spec.kind} with ` + source_item.type,
105
+ ),
106
+ );
107
+
108
+ // `ended` is what autoplay_media waits for instead of its timer; the
109
+ // reference is kept so dispose() can detach it, like the two above
110
+ this._onEnded = () => {
111
+ this.fire("media_ended", this.data);
112
+ };
113
+ media_item.addEventListener("ended", this._onEnded);
114
+
115
+ this.player_element = media_item;
116
+ }
117
+
118
+ // Update Media Display
119
+ _updateMediaDisplay() {
120
+ // the height is CSS-driven; nothing to compute here
121
+ }
122
+
123
+ _stopMedia() {
124
+ this.player_element?.pause();
125
+ }
126
+
127
+ /**
128
+ * Detach the media listeners and release the source, so a disposed audio
129
+ * or video element stops buffering instead of playing into a detached
130
+ * tree. Pausing alone (what `stopMedia()` does per slide change) is not
131
+ * enough for a full teardown.
132
+ */
133
+ _disposeMedia() {
134
+ if (this._onCanPlay) {
135
+ this.player_element?.removeEventListener("canplay", this._onCanPlay);
136
+ this._onCanPlay = null;
137
+ }
138
+ if (this._onEnded) {
139
+ this.player_element?.removeEventListener("ended", this._onEnded);
140
+ this._onEnded = null;
141
+ }
142
+ if (this._onSourceError) {
143
+ this._el.source_item?.removeEventListener("error", this._onSourceError);
144
+ this._onSourceError = null;
145
+ }
146
+ const el = this.player_element;
147
+ if (el) {
148
+ el.pause();
149
+ // dropping the source stops the network fetch immediately
150
+ el.removeAttribute("src");
151
+ el.load();
152
+ }
153
+ this.player_element = null;
154
+
155
+ this._onCanPlay = null;
156
+
157
+ this._onSourceError = null;
158
+ }
159
+
160
+ _getType(url: string, spec: HtmlMediaSpec): string {
161
+ const ext = url.match((this.data.mediatype as { match_str: string | RegExp }).match_str);
162
+ if (!ext) {
163
+ return "";
164
+ }
165
+ return mimeSubtype(ext[1], spec);
166
+ }
167
+ }
@@ -1,6 +1,5 @@
1
1
  import { Media } from "../Media";
2
2
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
4
3
  import { buildIframe } from "../EmbedUtil";
5
4
 
6
5
  /* Media.IFrame
@@ -13,7 +12,7 @@ export default class IFrame extends Media {
13
12
  ================================================== */
14
13
  _loadMedia() {
15
14
  // Loading Message
16
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
15
+ this.loadingMessage();
17
16
 
18
17
  // Create Dom element
19
18
  this._el.content_item = Dom.create(
@@ -23,7 +22,7 @@ export default class IFrame extends Media {
23
22
  );
24
23
 
25
24
  // Get Media ID
26
- this.media_id = this.data.url;
25
+ this.media_id = this._url();
27
26
 
28
27
  // The url field holds a user-pasted embed snippet. Rebuild a
29
28
  // clean iframe from its src instead of injecting the raw markup,
@@ -46,6 +45,6 @@ export default class IFrame extends Media {
46
45
 
47
46
  // Update Media Display
48
47
  _updateMediaDisplay() {
49
- this._el.content_item.style.height = this.options.height + "px";
48
+ this._sizeContentItemToOptionHeight();
50
49
  }
51
50
  }
@@ -1,6 +1,31 @@
1
1
  import { Media } from "../Media";
2
2
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
3
+ import { validateWebURL } from "../EmbedUtil";
4
+
5
+ /* IIIF Image API 2/3 URL tail: .../region/size/rotation/quality.format
6
+ (optionally a query string). Used to request container-matched widths
7
+ instead of the full-size image (perf, backwards-compatible). */
8
+ const IIIF_TAIL =
9
+ /\/(full|max|pct:[\d.]+|\d+,?\d*)\/(full|max|pct:[\d.]+|\d+,?\d*)\/(\d+|full)\/(default|color|gray|bitonal)\.(jpg|jpeg|png|webp|gif)(\?.*)?$/i;
10
+
11
+ /**
12
+ * Rewrite an IIIF Image API URL to the given pixel width (`w,` size
13
+ * component, height unconstrained). Returns the URL unchanged when it is
14
+ * not a recognizable IIIF image URL.
15
+ */
16
+ export function iiifSizedUrl(url: string | null, width: number): string | null {
17
+ if (!url || !(width > 0)) {
18
+ return url;
19
+ }
20
+ const match = url.match(IIIF_TAIL);
21
+ if (!match) {
22
+ return url;
23
+ }
24
+ return (
25
+ url.slice(0, match.index) +
26
+ `/${match[1]}/${width},/${match[3]}/${match[4]}.${match[5]}${match[6] ?? ""}`
27
+ );
28
+ }
4
29
 
5
30
  /* Media.Image
6
31
  Produces image assets.
@@ -12,14 +37,17 @@ export default class Image extends Media {
12
37
  ================================================== */
13
38
  _loadMedia() {
14
39
  // Loading Message
15
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
40
+ this.loadingMessage();
16
41
 
17
- // Link
18
- if (this.data.link) {
42
+ // Link — protocol-checked: a `javascript:` href in the storymap JSON
43
+ // would be a click-through XSS (see Media._initLayout)
44
+ const link_href = this.data.link ? validateWebURL(this.data.link) : null;
45
+ if (link_href) {
19
46
  this._el.content_link = Dom.create("a", "", this._el.content);
20
47
  const content_link = this._el.content_link as HTMLAnchorElement;
21
- content_link.href = this.data.link;
48
+ content_link.href = link_href;
22
49
  content_link.target = "_blank";
50
+ content_link.rel = "noopener noreferrer";
23
51
  this._el.content_item = Dom.create(
24
52
  "img",
25
53
  "vco-media-item vco-media-image vco-media-shadow",
@@ -38,11 +66,49 @@ export default class Image extends Media {
38
66
  this.onMediaLoaded();
39
67
  });
40
68
 
41
- (this._el.content_item as HTMLImageElement).src = this.data.url;
69
+ const img = this._el.content_item as HTMLImageElement;
70
+ // offscreen/preloaded slides stay lazy (the active slide is
71
+ // upgraded to eager on activation, see Slide.setActive); decoding
72
+ // is only a hint — old browsers ignore both attributes
73
+ img.decoding = "async";
74
+ img.loading = this._state.eager ? "eager" : "lazy";
75
+ // responsive sizes (perf): IIIF image URLs request a container-
76
+ // matched width; author-provided srcset/sizes pass through;
77
+ // everything else renders byte-identically
78
+ const media_width = Number(this.options.width) || 0;
79
+ const sized = iiifSizedUrl(this._url(), media_width);
80
+ img.src = sized ?? this._url();
81
+ // accessibility: explicit alt text, falling back to the caption as
82
+ // plain text; an empty string marks a decorative image
83
+ img.alt = this._altText();
84
+ if (this.data.srcset) {
85
+ img.srcset = this.data.srcset as string;
86
+ }
87
+ if (this.data.sizes) {
88
+ img.sizes = this.data.sizes as string;
89
+ }
42
90
 
91
+ // the element is built and the src is set: hand over to Media so the
92
+ // loading overlay is hidden and credit/caption are rendered. The
93
+ // `load` listener above only fires the separate media_loaded event.
43
94
  this.onLoaded();
44
95
  }
45
96
 
97
+ _altText(): string {
98
+ const alt = this.data.alt as string | undefined;
99
+ if (alt !== undefined && alt !== "") {
100
+ return alt;
101
+ }
102
+ const caption = this.data.caption as string | null | undefined;
103
+ if (caption) {
104
+ return caption
105
+ .replace(/<[^>]*>/g, " ")
106
+ .replace(/\s+/g, " ")
107
+ .trim();
108
+ }
109
+ return "";
110
+ }
111
+
46
112
  _updateMediaDisplay(layout?: string) {
47
113
  // modern browsers size media correctly without engine-specific fixes
48
114
  }
@@ -1,6 +1,6 @@
1
1
  import { Media } from "../Media";
2
2
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
3
+ import { buildIframe } from "../EmbedUtil";
4
4
 
5
5
  /* Media.Juxtapose
6
6
  Embeds a JuxtaposeJS before/after slider (issue #360)
@@ -11,7 +11,7 @@ export default class Juxtapose extends Media {
11
11
  ================================================== */
12
12
  _loadMedia() {
13
13
  // Loading Message
14
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
14
+ this.loadingMessage();
15
15
 
16
16
  // Create Dom element
17
17
  this._el.content_item = Dom.create(
@@ -20,13 +20,22 @@ export default class Juxtapose extends Media {
20
20
  this._el.content,
21
21
  );
22
22
 
23
- // published Juxtapose URLs are iframe-ready embeds
24
- this._el.content_item.innerHTML = `<iframe src="${this.data.url}" />`;
23
+ // Built through buildIframe rather than an `<iframe src="${url}">`
24
+ // template string: interpolating a storymap-JSON string into markup
25
+ // is a stored-XSS break-out (`"><img src=x onerror=...>`), and
26
+ // MediaType routes *any* URL containing "juxtapose" here.
27
+ const embed = buildIframe(`<iframe src="${String(this._url() ?? "")}"></iframe>`);
28
+ if (!embed) {
29
+ this.loadErrorDisplay("Invalid URL.");
30
+ return;
31
+ }
32
+ embed.setAttribute("loading", "lazy");
33
+ this._el.content_item.appendChild(embed);
25
34
  this.onLoaded();
26
35
  }
27
36
 
28
37
  // Update Media Display
29
38
  _updateMediaDisplay() {
30
- this._el.content_item.style.height = this.options.height + "px";
39
+ this._sizeContentItemToOptionHeight();
31
40
  }
32
41
  }
@@ -1,6 +1,6 @@
1
1
  import { Media } from "../Media";
2
2
  import Dom from "../../dom/Dom";
3
- import { Language } from "../../language/Language";
3
+ import { sanitizeSlideText } from "../EmbedUtil";
4
4
 
5
5
  /* Media.SoundCloud
6
6
  ================================================== */
@@ -8,18 +8,19 @@ import { Language } from "../../language/Language";
8
8
  /* Minimal surface of the SoundCloud widget API used here. */
9
9
  interface SoundCloudWidget {
10
10
  pause: () => void;
11
+ unbind?: () => void;
11
12
  }
12
13
 
13
14
  export default class SoundCloud extends Media {
14
15
  declare "media_id": string;
15
16
  declare "soundCloudCreated": boolean;
16
- declare "widget": SoundCloudWidget;
17
+ declare "widget": SoundCloudWidget | null;
17
18
 
18
19
  /* Load the media
19
20
  ================================================== */
20
21
  async _loadMedia() {
21
22
  // Loading Message
22
- this.message.updateMessage(Language.messages.loading + " " + this.options.media_name);
23
+ this.loadingMessage();
23
24
 
24
25
  // Create Dom element
25
26
  this._el.content_item = Dom.create(
@@ -29,7 +30,7 @@ export default class SoundCloud extends Media {
29
30
  );
30
31
 
31
32
  // Get Media ID
32
- this.media_id = this.data.url;
33
+ this.media_id = this._url();
33
34
 
34
35
  // API URL
35
36
  const api_url = "https://soundcloud.com/oembed?url=" + this.media_id + "&format=json";
@@ -56,14 +57,24 @@ export default class SoundCloud extends Media {
56
57
  this.loadErrorDisplay("Unable to load this track.");
57
58
  return;
58
59
  }
59
- this._el.content_item.innerHTML = data.html;
60
+ // The oEmbed response is third-party HTML. It is sanitized like any
61
+ // other untrusted markup, which in practice keeps the provider's
62
+ // <iframe> (rebuilt by the sanitizer) and drops its inline script —
63
+ // the widget is created from the iframe below, so the script was never
64
+ // needed in the first place.
65
+ const content_item = this._el.content_item;
66
+ if (!content_item) {
67
+ this.loadErrorDisplay("Unable to load this track.");
68
+ return;
69
+ }
70
+ content_item.appendChild(sanitizeSlideText(data.html));
60
71
 
61
72
  this.soundCloudCreated = true;
62
73
 
63
74
  const sc = SC as { Widget: (iframe: Element | null) => SoundCloudWidget };
64
75
  // per-instance widget: a global would be overwritten by every
65
76
  // SoundCloud slide and _stopMedia would pause the wrong one
66
- this.widget = sc.Widget(this._el.content_item.querySelector("iframe"));
77
+ this.widget = sc.Widget(content_item.querySelector("iframe"));
67
78
 
68
79
  // After Loaded
69
80
  this.onLoaded();
@@ -74,4 +85,15 @@ export default class SoundCloud extends Media {
74
85
  this.widget?.pause();
75
86
  }
76
87
  }
88
+
89
+ /** Unbind the widget so it stops playing once the slide is gone. */
90
+ _disposeMedia() {
91
+ try {
92
+ this.widget?.unbind?.();
93
+ } catch (err) {
94
+ console.log(err);
95
+ }
96
+ this.widget = null;
97
+ this.soundCloudCreated = false;
98
+ }
77
99
  }