@projektemacher/storymapjs 0.10.6 → 0.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (552) hide show
  1. package/CHANGELOG +358 -16
  2. package/README.md +43 -9
  3. package/dist/assets/demo-DBpeF31K.js +1 -0
  4. package/dist/assets/harness-Cr0rYpvt.js +1 -0
  5. package/dist/assets/harness-multi-CYHgI0a9.js +1 -0
  6. package/dist/assets/harness-support-Do7sIp2j.js +1 -0
  7. package/dist/assets/index-wHPqGrBS.js +1 -0
  8. package/dist/assets/main-DXalctuR.js +17 -0
  9. package/dist/context.json +12 -9
  10. package/dist/css/fonts/files/amatic-sc-cyrillic-400-normal.woff2 +0 -0
  11. package/dist/css/fonts/files/amatic-sc-cyrillic-700-normal.woff2 +0 -0
  12. package/dist/css/fonts/files/amatic-sc-hebrew-400-normal.woff2 +0 -0
  13. package/dist/css/fonts/files/amatic-sc-hebrew-700-normal.woff2 +0 -0
  14. package/dist/css/fonts/files/amatic-sc-vietnamese-400-normal.woff2 +0 -0
  15. package/dist/css/fonts/files/amatic-sc-vietnamese-700-normal.woff2 +0 -0
  16. package/dist/css/fonts/files/bitter-cyrillic-100-italic.woff2 +0 -0
  17. package/dist/css/fonts/files/bitter-cyrillic-100-normal.woff2 +0 -0
  18. package/dist/css/fonts/files/bitter-cyrillic-200-italic.woff2 +0 -0
  19. package/dist/css/fonts/files/bitter-cyrillic-200-normal.woff2 +0 -0
  20. package/dist/css/fonts/files/bitter-cyrillic-300-italic.woff2 +0 -0
  21. package/dist/css/fonts/files/bitter-cyrillic-300-normal.woff2 +0 -0
  22. package/dist/css/fonts/files/bitter-cyrillic-400-italic.woff2 +0 -0
  23. package/dist/css/fonts/files/bitter-cyrillic-400-normal.woff2 +0 -0
  24. package/dist/css/fonts/files/bitter-cyrillic-500-italic.woff2 +0 -0
  25. package/dist/css/fonts/files/bitter-cyrillic-500-normal.woff2 +0 -0
  26. package/dist/css/fonts/files/bitter-cyrillic-600-italic.woff2 +0 -0
  27. package/dist/css/fonts/files/bitter-cyrillic-600-normal.woff2 +0 -0
  28. package/dist/css/fonts/files/bitter-cyrillic-700-italic.woff2 +0 -0
  29. package/dist/css/fonts/files/bitter-cyrillic-700-normal.woff2 +0 -0
  30. package/dist/css/fonts/files/bitter-cyrillic-800-italic.woff2 +0 -0
  31. package/dist/css/fonts/files/bitter-cyrillic-800-normal.woff2 +0 -0
  32. package/dist/css/fonts/files/bitter-cyrillic-900-italic.woff2 +0 -0
  33. package/dist/css/fonts/files/bitter-cyrillic-900-normal.woff2 +0 -0
  34. package/dist/css/fonts/files/bitter-cyrillic-ext-100-italic.woff2 +0 -0
  35. package/dist/css/fonts/files/bitter-cyrillic-ext-100-normal.woff2 +0 -0
  36. package/dist/css/fonts/files/bitter-cyrillic-ext-200-italic.woff2 +0 -0
  37. package/dist/css/fonts/files/bitter-cyrillic-ext-200-normal.woff2 +0 -0
  38. package/dist/css/fonts/files/bitter-cyrillic-ext-300-italic.woff2 +0 -0
  39. package/dist/css/fonts/files/bitter-cyrillic-ext-300-normal.woff2 +0 -0
  40. package/dist/css/fonts/files/bitter-cyrillic-ext-400-italic.woff2 +0 -0
  41. package/dist/css/fonts/files/bitter-cyrillic-ext-400-normal.woff2 +0 -0
  42. package/dist/css/fonts/files/bitter-cyrillic-ext-500-italic.woff2 +0 -0
  43. package/dist/css/fonts/files/bitter-cyrillic-ext-500-normal.woff2 +0 -0
  44. package/dist/css/fonts/files/bitter-cyrillic-ext-600-italic.woff2 +0 -0
  45. package/dist/css/fonts/files/bitter-cyrillic-ext-600-normal.woff2 +0 -0
  46. package/dist/css/fonts/files/bitter-cyrillic-ext-700-italic.woff2 +0 -0
  47. package/dist/css/fonts/files/bitter-cyrillic-ext-700-normal.woff2 +0 -0
  48. package/dist/css/fonts/files/bitter-cyrillic-ext-800-italic.woff2 +0 -0
  49. package/dist/css/fonts/files/bitter-cyrillic-ext-800-normal.woff2 +0 -0
  50. package/dist/css/fonts/files/bitter-cyrillic-ext-900-italic.woff2 +0 -0
  51. package/dist/css/fonts/files/bitter-cyrillic-ext-900-normal.woff2 +0 -0
  52. package/dist/css/fonts/files/bitter-cyrillic-ext-wght-italic.woff2 +0 -0
  53. package/dist/css/fonts/files/bitter-cyrillic-ext-wght-normal.woff2 +0 -0
  54. package/dist/css/fonts/files/bitter-cyrillic-wght-italic.woff2 +0 -0
  55. package/dist/css/fonts/files/bitter-cyrillic-wght-normal.woff2 +0 -0
  56. package/dist/css/fonts/files/bitter-vietnamese-100-italic.woff2 +0 -0
  57. package/dist/css/fonts/files/bitter-vietnamese-100-normal.woff2 +0 -0
  58. package/dist/css/fonts/files/bitter-vietnamese-200-italic.woff2 +0 -0
  59. package/dist/css/fonts/files/bitter-vietnamese-200-normal.woff2 +0 -0
  60. package/dist/css/fonts/files/bitter-vietnamese-300-italic.woff2 +0 -0
  61. package/dist/css/fonts/files/bitter-vietnamese-300-normal.woff2 +0 -0
  62. package/dist/css/fonts/files/bitter-vietnamese-400-italic.woff2 +0 -0
  63. package/dist/css/fonts/files/bitter-vietnamese-400-normal.woff2 +0 -0
  64. package/dist/css/fonts/files/bitter-vietnamese-500-italic.woff2 +0 -0
  65. package/dist/css/fonts/files/bitter-vietnamese-500-normal.woff2 +0 -0
  66. package/dist/css/fonts/files/bitter-vietnamese-600-italic.woff2 +0 -0
  67. package/dist/css/fonts/files/bitter-vietnamese-600-normal.woff2 +0 -0
  68. package/dist/css/fonts/files/bitter-vietnamese-700-italic.woff2 +0 -0
  69. package/dist/css/fonts/files/bitter-vietnamese-700-normal.woff2 +0 -0
  70. package/dist/css/fonts/files/bitter-vietnamese-800-italic.woff2 +0 -0
  71. package/dist/css/fonts/files/bitter-vietnamese-800-normal.woff2 +0 -0
  72. package/dist/css/fonts/files/bitter-vietnamese-900-italic.woff2 +0 -0
  73. package/dist/css/fonts/files/bitter-vietnamese-900-normal.woff2 +0 -0
  74. package/dist/css/fonts/files/bitter-vietnamese-wght-italic.woff2 +0 -0
  75. package/dist/css/fonts/files/bitter-vietnamese-wght-normal.woff2 +0 -0
  76. package/dist/css/fonts/files/cairo-arabic-200-normal.woff2 +0 -0
  77. package/dist/css/fonts/files/cairo-arabic-300-normal.woff2 +0 -0
  78. package/dist/css/fonts/files/cairo-arabic-400-normal.woff2 +0 -0
  79. package/dist/css/fonts/files/cairo-arabic-500-normal.woff2 +0 -0
  80. package/dist/css/fonts/files/cairo-arabic-600-normal.woff2 +0 -0
  81. package/dist/css/fonts/files/cairo-arabic-700-normal.woff2 +0 -0
  82. package/dist/css/fonts/files/cairo-arabic-800-normal.woff2 +0 -0
  83. package/dist/css/fonts/files/cairo-arabic-900-normal.woff2 +0 -0
  84. package/dist/css/fonts/files/cairo-latin-200-normal.woff2 +0 -0
  85. package/dist/css/fonts/files/cairo-latin-300-normal.woff2 +0 -0
  86. package/dist/css/fonts/files/cairo-latin-400-normal.woff2 +0 -0
  87. package/dist/css/fonts/files/cairo-latin-500-normal.woff2 +0 -0
  88. package/dist/css/fonts/files/cairo-latin-600-normal.woff2 +0 -0
  89. package/dist/css/fonts/files/cairo-latin-700-normal.woff2 +0 -0
  90. package/dist/css/fonts/files/cairo-latin-800-normal.woff2 +0 -0
  91. package/dist/css/fonts/files/cairo-latin-900-normal.woff2 +0 -0
  92. package/dist/css/fonts/files/cairo-latin-ext-200-normal.woff2 +0 -0
  93. package/dist/css/fonts/files/cairo-latin-ext-300-normal.woff2 +0 -0
  94. package/dist/css/fonts/files/cairo-latin-ext-400-normal.woff2 +0 -0
  95. package/dist/css/fonts/files/cairo-latin-ext-500-normal.woff2 +0 -0
  96. package/dist/css/fonts/files/cairo-latin-ext-600-normal.woff2 +0 -0
  97. package/dist/css/fonts/files/cairo-latin-ext-700-normal.woff2 +0 -0
  98. package/dist/css/fonts/files/cairo-latin-ext-800-normal.woff2 +0 -0
  99. package/dist/css/fonts/files/cairo-latin-ext-900-normal.woff2 +0 -0
  100. package/dist/css/fonts/files/dancing-script-vietnamese-wght-normal.woff2 +0 -0
  101. package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-italic.woff2 +0 -0
  102. package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-normal.woff2 +0 -0
  103. package/dist/css/fonts/files/eb-garamond-cyrillic-wght-italic.woff2 +0 -0
  104. package/dist/css/fonts/files/eb-garamond-cyrillic-wght-normal.woff2 +0 -0
  105. package/dist/css/fonts/files/eb-garamond-greek-ext-wght-italic.woff2 +0 -0
  106. package/dist/css/fonts/files/eb-garamond-greek-ext-wght-normal.woff2 +0 -0
  107. package/dist/css/fonts/files/eb-garamond-greek-wght-italic.woff2 +0 -0
  108. package/dist/css/fonts/files/eb-garamond-greek-wght-normal.woff2 +0 -0
  109. package/dist/css/fonts/files/eb-garamond-vietnamese-wght-italic.woff2 +0 -0
  110. package/dist/css/fonts/files/eb-garamond-vietnamese-wght-normal.woff2 +0 -0
  111. package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-italic.woff2 +0 -0
  112. package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-normal.woff2 +0 -0
  113. package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-italic.woff2 +0 -0
  114. package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-normal.woff2 +0 -0
  115. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-italic.woff2 +0 -0
  116. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-normal.woff2 +0 -0
  117. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-italic.woff2 +0 -0
  118. package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-normal.woff2 +0 -0
  119. package/dist/css/fonts/files/gentium-book-plus-greek-400-italic.woff2 +0 -0
  120. package/dist/css/fonts/files/gentium-book-plus-greek-400-normal.woff2 +0 -0
  121. package/dist/css/fonts/files/gentium-book-plus-greek-700-italic.woff2 +0 -0
  122. package/dist/css/fonts/files/gentium-book-plus-greek-700-normal.woff2 +0 -0
  123. package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-italic.woff2 +0 -0
  124. package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-normal.woff2 +0 -0
  125. package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-italic.woff2 +0 -0
  126. package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-normal.woff2 +0 -0
  127. package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-italic.woff2 +0 -0
  128. package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-normal.woff2 +0 -0
  129. package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-italic.woff2 +0 -0
  130. package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-normal.woff2 +0 -0
  131. package/dist/css/fonts/files/old-standard-tt-cyrillic-400-italic.woff2 +0 -0
  132. package/dist/css/fonts/files/old-standard-tt-cyrillic-400-normal.woff2 +0 -0
  133. package/dist/css/fonts/files/old-standard-tt-cyrillic-700-normal.woff2 +0 -0
  134. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-italic.woff2 +0 -0
  135. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-normal.woff2 +0 -0
  136. package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-700-normal.woff2 +0 -0
  137. package/dist/css/fonts/files/old-standard-tt-vietnamese-400-italic.woff2 +0 -0
  138. package/dist/css/fonts/files/old-standard-tt-vietnamese-400-normal.woff2 +0 -0
  139. package/dist/css/fonts/files/old-standard-tt-vietnamese-700-normal.woff2 +0 -0
  140. package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-italic.woff2 +0 -0
  141. package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-normal.woff2 +0 -0
  142. package/dist/css/fonts/files/open-sans-cyrillic-wght-italic.woff2 +0 -0
  143. package/dist/css/fonts/files/open-sans-cyrillic-wght-normal.woff2 +0 -0
  144. package/dist/css/fonts/files/open-sans-greek-ext-wght-italic.woff2 +0 -0
  145. package/dist/css/fonts/files/open-sans-greek-ext-wght-normal.woff2 +0 -0
  146. package/dist/css/fonts/files/open-sans-greek-wght-italic.woff2 +0 -0
  147. package/dist/css/fonts/files/open-sans-greek-wght-normal.woff2 +0 -0
  148. package/dist/css/fonts/files/open-sans-hebrew-wght-italic.woff2 +0 -0
  149. package/dist/css/fonts/files/open-sans-hebrew-wght-normal.woff2 +0 -0
  150. package/dist/css/fonts/files/open-sans-vietnamese-wght-italic.woff2 +0 -0
  151. package/dist/css/fonts/files/open-sans-vietnamese-wght-normal.woff2 +0 -0
  152. package/dist/css/fonts/files/playfair-display-cyrillic-wght-italic.woff2 +0 -0
  153. package/dist/css/fonts/files/playfair-display-cyrillic-wght-normal.woff2 +0 -0
  154. package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-italic.woff2 +0 -0
  155. package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-normal.woff2 +0 -0
  156. package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-italic.woff2 +0 -0
  157. package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-normal.woff2 +0 -0
  158. package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-italic.woff2 +0 -0
  159. package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-normal.woff2 +0 -0
  160. package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-italic.woff2 +0 -0
  161. package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-normal.woff2 +0 -0
  162. package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-italic.woff2 +0 -0
  163. package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-normal.woff2 +0 -0
  164. package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-italic.woff2 +0 -0
  165. package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-normal.woff2 +0 -0
  166. package/dist/css/fonts/files/playfair-display-vietnamese-wght-italic.woff2 +0 -0
  167. package/dist/css/fonts/files/playfair-display-vietnamese-wght-normal.woff2 +0 -0
  168. package/dist/css/fonts/files/pt-sans-cyrillic-400-italic.woff2 +0 -0
  169. package/dist/css/fonts/files/pt-sans-cyrillic-400-normal.woff2 +0 -0
  170. package/dist/css/fonts/files/pt-sans-cyrillic-700-italic.woff2 +0 -0
  171. package/dist/css/fonts/files/pt-sans-cyrillic-700-normal.woff2 +0 -0
  172. package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-italic.woff2 +0 -0
  173. package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-normal.woff2 +0 -0
  174. package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-italic.woff2 +0 -0
  175. package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-normal.woff2 +0 -0
  176. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-400-normal.woff2 +0 -0
  177. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-700-normal.woff2 +0 -0
  178. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-400-normal.woff2 +0 -0
  179. package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-700-normal.woff2 +0 -0
  180. package/dist/css/fonts/files/pt-serif-cyrillic-400-italic.woff2 +0 -0
  181. package/dist/css/fonts/files/pt-serif-cyrillic-400-normal.woff2 +0 -0
  182. package/dist/css/fonts/files/pt-serif-cyrillic-700-italic.woff2 +0 -0
  183. package/dist/css/fonts/files/pt-serif-cyrillic-700-normal.woff2 +0 -0
  184. package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-italic.woff2 +0 -0
  185. package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-normal.woff2 +0 -0
  186. package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-italic.woff2 +0 -0
  187. package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-normal.woff2 +0 -0
  188. package/dist/css/fonts/files/raleway-cyrillic-ext-wght-italic.woff2 +0 -0
  189. package/dist/css/fonts/files/raleway-cyrillic-ext-wght-normal.woff2 +0 -0
  190. package/dist/css/fonts/files/raleway-cyrillic-wght-italic.woff2 +0 -0
  191. package/dist/css/fonts/files/raleway-cyrillic-wght-normal.woff2 +0 -0
  192. package/dist/css/fonts/files/raleway-vietnamese-wght-italic.woff2 +0 -0
  193. package/dist/css/fonts/files/raleway-vietnamese-wght-normal.woff2 +0 -0
  194. package/dist/css/fonts/files/roboto-slab-cyrillic-ext-wght-normal.woff2 +0 -0
  195. package/dist/css/fonts/files/roboto-slab-cyrillic-wght-normal.woff2 +0 -0
  196. package/dist/css/fonts/files/roboto-slab-greek-ext-wght-normal.woff2 +0 -0
  197. package/dist/css/fonts/files/roboto-slab-greek-wght-normal.woff2 +0 -0
  198. package/dist/css/fonts/files/roboto-slab-vietnamese-wght-normal.woff2 +0 -0
  199. package/dist/css/fonts/files/ubuntu-cyrillic-300-italic.woff2 +0 -0
  200. package/dist/css/fonts/files/ubuntu-cyrillic-300-normal.woff2 +0 -0
  201. package/dist/css/fonts/files/ubuntu-cyrillic-400-italic.woff2 +0 -0
  202. package/dist/css/fonts/files/ubuntu-cyrillic-400-normal.woff2 +0 -0
  203. package/dist/css/fonts/files/ubuntu-cyrillic-500-italic.woff2 +0 -0
  204. package/dist/css/fonts/files/ubuntu-cyrillic-500-normal.woff2 +0 -0
  205. package/dist/css/fonts/files/ubuntu-cyrillic-700-italic.woff2 +0 -0
  206. package/dist/css/fonts/files/ubuntu-cyrillic-700-normal.woff2 +0 -0
  207. package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-italic.woff2 +0 -0
  208. package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-normal.woff2 +0 -0
  209. package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-italic.woff2 +0 -0
  210. package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-normal.woff2 +0 -0
  211. package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-italic.woff2 +0 -0
  212. package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-normal.woff2 +0 -0
  213. package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-italic.woff2 +0 -0
  214. package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-normal.woff2 +0 -0
  215. package/dist/css/fonts/files/ubuntu-greek-300-italic.woff2 +0 -0
  216. package/dist/css/fonts/files/ubuntu-greek-300-normal.woff2 +0 -0
  217. package/dist/css/fonts/files/ubuntu-greek-400-italic.woff2 +0 -0
  218. package/dist/css/fonts/files/ubuntu-greek-400-normal.woff2 +0 -0
  219. package/dist/css/fonts/files/ubuntu-greek-500-italic.woff2 +0 -0
  220. package/dist/css/fonts/files/ubuntu-greek-500-normal.woff2 +0 -0
  221. package/dist/css/fonts/files/ubuntu-greek-700-italic.woff2 +0 -0
  222. package/dist/css/fonts/files/ubuntu-greek-700-normal.woff2 +0 -0
  223. package/dist/css/fonts/files/ubuntu-greek-ext-300-italic.woff2 +0 -0
  224. package/dist/css/fonts/files/ubuntu-greek-ext-300-normal.woff2 +0 -0
  225. package/dist/css/fonts/files/ubuntu-greek-ext-400-italic.woff2 +0 -0
  226. package/dist/css/fonts/files/ubuntu-greek-ext-400-normal.woff2 +0 -0
  227. package/dist/css/fonts/files/ubuntu-greek-ext-500-italic.woff2 +0 -0
  228. package/dist/css/fonts/files/ubuntu-greek-ext-500-normal.woff2 +0 -0
  229. package/dist/css/fonts/files/ubuntu-greek-ext-700-italic.woff2 +0 -0
  230. package/dist/css/fonts/files/ubuntu-greek-ext-700-normal.woff2 +0 -0
  231. package/dist/css/fonts/files/unica-one-vietnamese-400-normal.woff2 +0 -0
  232. package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-italic.woff2 +0 -0
  233. package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-normal.woff2 +0 -0
  234. package/dist/css/fonts/files/vollkorn-cyrillic-wght-italic.woff2 +0 -0
  235. package/dist/css/fonts/files/vollkorn-cyrillic-wght-normal.woff2 +0 -0
  236. package/dist/css/fonts/files/vollkorn-greek-wght-italic.woff2 +0 -0
  237. package/dist/css/fonts/files/vollkorn-greek-wght-normal.woff2 +0 -0
  238. package/dist/css/fonts/files/vollkorn-vietnamese-wght-italic.woff2 +0 -0
  239. package/dist/css/fonts/files/vollkorn-vietnamese-wght-normal.woff2 +0 -0
  240. package/dist/css/fonts/font.abril-droidsans.css +3 -0
  241. package/dist/css/fonts/font.amatic-andika.css +57 -0
  242. package/dist/css/fonts/font.bitter-raleway.css +111 -0
  243. package/dist/css/fonts/font.cairo.css +312 -0
  244. package/dist/css/fonts/font.clicker-garamond.css +93 -0
  245. package/dist/css/fonts/font.dancing-ledger.css +12 -0
  246. package/dist/css/fonts/font.default.css +183 -0
  247. package/dist/css/fonts/font.fjalla-average.css +3 -0
  248. package/dist/css/fonts/font.georgia-helvetica.css +3 -0
  249. package/dist/css/fonts/font.knightlab.css +642 -0
  250. package/dist/css/fonts/font.lustria-lato.css +3 -0
  251. package/dist/css/fonts/font.medula-lato.css +3 -0
  252. package/dist/css/fonts/font.oldstandard.css +101 -21
  253. package/dist/css/fonts/font.opensans-gentiumbook.css +183 -0
  254. package/dist/css/fonts/font.playfair-faunaone.css +39 -0
  255. package/dist/css/fonts/font.playfair.css +147 -0
  256. package/dist/css/fonts/font.pt.css +183 -0
  257. package/dist/css/fonts/font.roboto-megrim.css +3 -0
  258. package/dist/css/fonts/font.rufina-sintony.css +3 -0
  259. package/dist/css/fonts/font.ubuntu.css +291 -0
  260. package/dist/css/fonts/font.unicaone-vollkorn.css +84 -0
  261. package/dist/css/storymap.css +1 -1
  262. package/dist/demo.html +2 -2
  263. package/dist/docs/api/.nojekyll +1 -0
  264. package/dist/docs/api/assets/custom.css +47 -0
  265. package/dist/docs/api/assets/hierarchy.js +1 -0
  266. package/dist/docs/api/assets/highlight.css +57 -0
  267. package/dist/docs/api/assets/icons.js +18 -0
  268. package/dist/docs/api/assets/icons.svg +1 -0
  269. package/dist/docs/api/assets/main.js +60 -0
  270. package/dist/docs/api/assets/navigation.js +1 -0
  271. package/dist/docs/api/assets/search.js +1 -0
  272. package/dist/docs/api/assets/style.css +1648 -0
  273. package/dist/docs/api/classes/StoryMap.html +1604 -0
  274. package/dist/docs/api/functions/MediaType.html +51 -0
  275. package/dist/docs/api/functions/isPresentation3Collection.html +47 -0
  276. package/dist/docs/api/functions/isPresentation3Manifest.html +53 -0
  277. package/dist/docs/api/functions/loadCSS.html +63 -0
  278. package/dist/docs/api/functions/manifestToStorymapData.html +49 -0
  279. package/dist/docs/api/functions/setLanguage.html +54 -0
  280. package/dist/docs/api/functions/storymapToManifest.html +57 -0
  281. package/dist/docs/api/functions/validateStorymap.html +53 -0
  282. package/dist/docs/api/functions/validateStorymapAndReport.html +54 -0
  283. package/dist/docs/api/hierarchy.html +28 -0
  284. package/dist/docs/api/index.html +197 -0
  285. package/dist/docs/api/interfaces/AnimationHandle.html +60 -0
  286. package/dist/docs/api/interfaces/ImagereadyPayload.html +71 -0
  287. package/dist/docs/api/interfaces/LanguageEntry.html +102 -0
  288. package/dist/docs/api/interfaces/LatLngLiteral.html +73 -0
  289. package/dist/docs/api/interfaces/LoadOptions.html +59 -0
  290. package/dist/docs/api/interfaces/OlLayer.html +1400 -0
  291. package/dist/docs/api/interfaces/OlMap.html +1656 -0
  292. package/dist/docs/api/interfaces/OlProjection.html +332 -0
  293. package/dist/docs/api/interfaces/OlSource.html +784 -0
  294. package/dist/docs/api/interfaces/OlTileLayer.html +1497 -0
  295. package/dist/docs/api/interfaces/OlVectorLayer.html +1559 -0
  296. package/dist/docs/api/interfaces/OlView.html +1958 -0
  297. package/dist/docs/api/interfaces/StorymapData.html +71 -0
  298. package/dist/docs/api/interfaces/StorymapDataWrapper.html +60 -0
  299. package/dist/docs/api/interfaces/StorymapDocument.html +68 -0
  300. package/dist/docs/api/interfaces/StorymapError.html +63 -0
  301. package/dist/docs/api/interfaces/StorymapGeoreference.html +93 -0
  302. package/dist/docs/api/interfaces/StorymapGeoreferenceBody.html +74 -0
  303. package/dist/docs/api/interfaces/StorymapGroundControlPoint.html +69 -0
  304. package/dist/docs/api/interfaces/StorymapLanguageMap.html +57 -0
  305. package/dist/docs/api/interfaces/StorymapManifest.html +118 -0
  306. package/dist/docs/api/interfaces/StorymapManifestAnnotation.html +105 -0
  307. package/dist/docs/api/interfaces/StorymapManifestBackground.html +81 -0
  308. package/dist/docs/api/interfaces/StorymapManifestCanvas.html +140 -0
  309. package/dist/docs/api/interfaces/StorymapManifestContentResource.html +97 -0
  310. package/dist/docs/api/interfaces/StorymapManifestFeatureCollection.html +82 -0
  311. package/dist/docs/api/interfaces/StorymapManifestGeoreferencing.html +87 -0
  312. package/dist/docs/api/interfaces/StorymapManifestImageService.html +69 -0
  313. package/dist/docs/api/interfaces/StorymapManifestRange.html +75 -0
  314. package/dist/docs/api/interfaces/StorymapManifestService.html +77 -0
  315. package/dist/docs/api/interfaces/StorymapManifestSpecificResource.html +69 -0
  316. package/dist/docs/api/interfaces/StorymapManifestStatement.html +63 -0
  317. package/dist/docs/api/interfaces/StorymapMapOptions.html +92 -0
  318. package/dist/docs/api/interfaces/StorymapOptions.html +532 -0
  319. package/dist/docs/api/interfaces/StorymapOverlayLayer.html +126 -0
  320. package/dist/docs/api/interfaces/StorymapSlide.html +132 -0
  321. package/dist/docs/api/interfaces/StorymapSlideBackground.html +72 -0
  322. package/dist/docs/api/interfaces/StorymapSlideLocation.html +117 -0
  323. package/dist/docs/api/interfaces/StorymapSlideMarker.html +104 -0
  324. package/dist/docs/api/interfaces/StorymapSlideMedia.html +110 -0
  325. package/dist/docs/api/interfaces/StorymapSlideNarration.html +65 -0
  326. package/dist/docs/api/interfaces/StorymapSlideText.html +72 -0
  327. package/dist/docs/api/interfaces/StorymapTilejson.html +105 -0
  328. package/dist/docs/api/media/es.json +31 -0
  329. package/dist/docs/api/media/migration-from-knightlab.md +359 -0
  330. package/dist/docs/api/modules.html +50 -0
  331. package/dist/docs/api/types/ContentState.html +70 -0
  332. package/dist/docs/api/types/ImagereadyKind.html +34 -0
  333. package/dist/docs/api/types/MediaTypeMatch.html +78 -0
  334. package/dist/docs/api/types/TileSourceFactory.html +53 -0
  335. package/dist/docs/authoring.html +293 -0
  336. package/dist/docs/iiif.html +617 -62
  337. package/dist/docs/migration.html +314 -12
  338. package/dist/docs/readme.html +40 -9
  339. package/dist/embed/index.html +130 -5
  340. package/dist/examples/issue-242-nonlatin.json +55 -0
  341. package/dist/examples/issue-305-start-at-slide-data.json +96 -0
  342. package/dist/examples/issue-358-iframe.json +57 -0
  343. package/dist/examples/issue-iiif-geo.json +32 -0
  344. package/dist/examples/issue-image-alt.json +23 -0
  345. package/dist/examples/issue-image-region.json +42 -0
  346. package/dist/examples/issue-image-srcset.json +24 -0
  347. package/dist/examples/map-area-overlays.json +68 -0
  348. package/dist/examples/no-map.json +44 -0
  349. package/dist/examples-iiif/annotated-image.json +188 -0
  350. package/dist/examples-iiif/bob-boilen.json +11 -5
  351. package/dist/examples-iiif/courbet.json +9 -6
  352. package/dist/examples-iiif/empty.json +8 -4
  353. package/dist/examples-iiif/flickr-drewvigal.json +248 -24
  354. package/dist/examples-iiif/flickr-zach.wise.json +8 -4
  355. package/dist/examples-iiif/georeferenced-layer-unsupported.json +153 -0
  356. package/dist/examples-iiif/georeferenced-layer.json +318 -0
  357. package/dist/examples-iiif/iiif-wellcome.json +9 -6
  358. package/dist/examples-iiif/instagram-chenpamela.json +381 -36
  359. package/dist/examples-iiif/instagram_brentfoster.json +429 -40
  360. package/dist/examples-iiif/instagram_couch.json +261 -26
  361. package/dist/examples-iiif/instagram_joegermuska.json +441 -41
  362. package/dist/examples-iiif/instagram_matteich.json +261 -26
  363. package/dist/examples-iiif/instagram_mirandamulligan.json +261 -26
  364. package/dist/examples-iiif/instagram_raymondmccrea.json +261 -26
  365. package/dist/examples-iiif/instagram_test.json +261 -26
  366. package/dist/examples-iiif/issue-134-no-lines.json +9 -5
  367. package/dist/examples-iiif/issue-177-color-vars.json +9 -5
  368. package/dist/examples-iiif/issue-211-rtl.json +9 -5
  369. package/dist/examples-iiif/issue-242-nonlatin.json +239 -0
  370. package/dist/examples-iiif/issue-272-facebook.json +9 -5
  371. package/dist/examples-iiif/issue-305-start-at-slide-data.json +305 -0
  372. package/dist/examples-iiif/issue-305-start-at-slide.json +9 -5
  373. package/dist/examples-iiif/issue-341-distance.json +9 -5
  374. package/dist/examples-iiif/issue-358-iframe.json +190 -0
  375. package/dist/examples-iiif/issue-360-juxtapose.json +22 -7
  376. package/dist/examples-iiif/issue-368-null-fields.json +9 -5
  377. package/dist/examples-iiif/issue-375-code-lists.json +9 -5
  378. package/dist/examples-iiif/issue-381-dateline.json +9 -5
  379. package/dist/examples-iiif/issue-405-custom-icon.json +203 -0
  380. package/dist/examples-iiif/issue-425-many-slides.json +9 -5
  381. package/dist/examples-iiif/issue-428-background.json +20 -8
  382. package/dist/examples-iiif/issue-435-googlemaps.json +9 -5
  383. package/dist/examples-iiif/issue-437-documentcloud.json +22 -7
  384. package/dist/examples-iiif/issue-451-webp.json +9 -5
  385. package/dist/examples-iiif/issue-455-audio.json +9 -5
  386. package/dist/examples-iiif/issue-480-shorts.json +9 -5
  387. package/dist/examples-iiif/issue-506-marker-sync.json +9 -5
  388. package/dist/examples-iiif/issue-iiif-geo.json +200 -0
  389. package/dist/examples-iiif/issue-image-alt.json +90 -0
  390. package/dist/examples-iiif/issue-image-region.json +203 -0
  391. package/dist/examples-iiif/issue-image-srcset.json +87 -0
  392. package/dist/examples-iiif/jansteen.json +9 -6
  393. package/dist/examples-iiif/katrina.json +197 -41
  394. package/dist/examples-iiif/map-area-overlays.json +289 -0
  395. package/dist/examples-iiif/marktwain.json +255 -58
  396. package/dist/examples-iiif/no-map.json +148 -0
  397. package/dist/examples-iiif/population.json +440 -76
  398. package/dist/examples-iiif/president.json +456 -83
  399. package/dist/examples-iiif/scroll-hint.json +190 -0
  400. package/dist/examples-iiif/seurat.json +113 -22
  401. package/dist/examples-iiif/zoomify-clamp.json +153 -0
  402. package/dist/harness-multi.html +17 -0
  403. package/dist/harness.html +3 -2
  404. package/dist/index.html +33 -10
  405. package/dist/js/storymap.d.ts +1558 -114
  406. package/dist/js/storymap.js +10113 -6490
  407. package/dist/js/storymap.js.map +1 -1
  408. package/dist/navplace-properties.json +40 -0
  409. package/docs/migration-from-knightlab.md +359 -0
  410. package/docs/storymap-as-iiif-manifest.md +934 -0
  411. package/package.json +16 -10
  412. package/schema/storymap.schema.json +431 -78
  413. package/src/animation/easings.ts +25 -0
  414. package/src/animation/tween.ts +186 -0
  415. package/src/core/Browser.ts +20 -0
  416. package/src/core/Load.ts +232 -0
  417. package/src/core/Util.ts +416 -0
  418. package/src/core/mixins.ts +188 -0
  419. package/src/core/viewers.ts +94 -0
  420. package/src/dom/Dom.ts +31 -0
  421. package/src/dom/DomEvent.ts +80 -0
  422. package/src/globals.d.ts +24 -0
  423. package/src/language/Language.ts +281 -0
  424. package/src/language/locale/.expected-gaps.json +86 -0
  425. package/src/language/locale/be.json +31 -0
  426. package/src/language/locale/bg.json +31 -0
  427. package/src/language/locale/cs.json +31 -0
  428. package/src/language/locale/de.json +31 -0
  429. package/src/language/locale/el.json +31 -0
  430. package/src/language/locale/en.json +32 -0
  431. package/src/language/locale/es.json +31 -0
  432. package/src/language/locale/et.json +22 -0
  433. package/src/language/locale/fr.json +31 -0
  434. package/src/language/locale/he.json +31 -0
  435. package/src/language/locale/hu.json +31 -0
  436. package/src/language/locale/is.json +22 -0
  437. package/src/language/locale/it.json +31 -0
  438. package/src/language/locale/jp.json +31 -0
  439. package/src/language/locale/ko.json +31 -0
  440. package/src/language/locale/nl.json +31 -0
  441. package/src/language/locale/nn.json +22 -0
  442. package/src/language/locale/no.json +31 -0
  443. package/src/language/locale/pl.json +31 -0
  444. package/src/language/locale/pt.json +31 -0
  445. package/src/language/locale/ru.json +31 -0
  446. package/src/language/locale/sk.json +31 -0
  447. package/src/language/locale/sr.json +21 -0
  448. package/src/language/locale/sv.json +31 -0
  449. package/src/language/locale/tr.json +31 -0
  450. package/src/language/locale/uk.json +31 -0
  451. package/src/language/locale/ur.json +22 -0
  452. package/src/language/locale/zh-cn.json +31 -0
  453. package/src/language/locale/zh-tw.json +31 -0
  454. package/src/main.ts +143 -0
  455. package/src/map/Map.ts +794 -0
  456. package/src/map/MapMarker.ts +172 -0
  457. package/src/map/georeference.ts +325 -0
  458. package/src/map/openlayers/Map.OpenLayers.ts +2492 -0
  459. package/src/map/openlayers/MapMarker.OpenLayers.ts +400 -0
  460. package/src/map/openlayers/zoomifyTiles.ts +25 -0
  461. package/src/map/types.ts +17 -0
  462. package/src/media/EmbedUtil.ts +452 -0
  463. package/src/media/Media.ts +597 -0
  464. package/src/media/MediaType.ts +163 -0
  465. package/src/media/embedId.ts +104 -0
  466. package/src/media/types/Audio.ts +14 -0
  467. package/src/media/types/Blockquote.ts +39 -0
  468. package/src/media/types/DailyMotion.ts +53 -0
  469. package/src/media/types/DocumentCloud.ts +12 -0
  470. package/src/media/types/Facebook.ts +40 -0
  471. package/src/media/types/Flickr.ts +115 -0
  472. package/src/media/types/GoogleDoc.ts +58 -0
  473. package/src/media/types/HtmlMedia.ts +167 -0
  474. package/src/media/types/IFrame.ts +50 -0
  475. package/src/media/types/Image.ts +115 -0
  476. package/src/media/types/Juxtapose.ts +41 -0
  477. package/src/media/types/SoundCloud.ts +99 -0
  478. package/src/media/types/Text.ts +178 -0
  479. package/src/media/types/Twitter.ts +109 -0
  480. package/src/media/types/Video.ts +14 -0
  481. package/src/media/types/Vimeo.ts +65 -0
  482. package/src/media/types/Website.ts +46 -0
  483. package/src/media/types/Wikipedia.ts +134 -0
  484. package/src/media/types/YouTube.ts +224 -0
  485. package/src/scss/Typography.scss +235 -0
  486. package/src/scss/VCO.StoryMap.Dark.scss +150 -0
  487. package/src/scss/VCO.StoryMap.scss +195 -0
  488. package/src/scss/Variables.Dark.scss +57 -0
  489. package/src/scss/Variables.scss +48 -0
  490. package/src/scss/core/Mixins.scss +54 -0
  491. package/src/scss/core/Reset.scss +206 -0
  492. package/src/scss/fonts/_font.base.scss +113 -0
  493. package/src/scss/fonts/font.abril-droidsans.scss +75 -0
  494. package/src/scss/fonts/font.amatic-andika.scss +76 -0
  495. package/src/scss/fonts/font.bitter-raleway.scss +92 -0
  496. package/src/scss/fonts/font.cairo.scss +79 -0
  497. package/src/scss/fonts/font.clicker-garamond.scss +97 -0
  498. package/src/scss/fonts/font.dancing-ledger.scss +75 -0
  499. package/src/scss/fonts/font.default.scss +9 -0
  500. package/src/scss/fonts/font.fjalla-average.scss +80 -0
  501. package/src/scss/fonts/font.georgia-helvetica.scss +58 -0
  502. package/src/scss/fonts/font.knightlab.scss +111 -0
  503. package/src/scss/fonts/font.lustria-lato.scss +80 -0
  504. package/src/scss/fonts/font.medula-lato.scss +73 -0
  505. package/src/scss/fonts/font.oldstandard.scss +94 -0
  506. package/src/scss/fonts/font.opensans-gentiumbook.scss +85 -0
  507. package/src/scss/fonts/font.playfair-faunaone.scss +88 -0
  508. package/src/scss/fonts/font.playfair.scss +89 -0
  509. package/src/scss/fonts/font.pt.scss +96 -0
  510. package/src/scss/fonts/font.roboto-megrim.scss +73 -0
  511. package/src/scss/fonts/font.rufina-sintony.scss +73 -0
  512. package/src/scss/fonts/font.ubuntu.scss +82 -0
  513. package/src/scss/fonts/font.unicaone-vollkorn.scss +90 -0
  514. package/src/scss/icons/Icons.scss +239 -0
  515. package/src/scss/map/VCO.ImageMarker.scss +23 -0
  516. package/src/scss/map/VCO.Map.scss +21 -0
  517. package/src/scss/map/VCO.MapMarker.scss +242 -0
  518. package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +126 -0
  519. package/src/scss/media/VCO.Media.scss +219 -0
  520. package/src/scss/media/types/VCO.Media.Blockquote.scss +76 -0
  521. package/src/scss/media/types/VCO.Media.IFrame.scss +11 -0
  522. package/src/scss/media/types/VCO.Media.Image.scss +13 -0
  523. package/src/scss/media/types/VCO.Media.Text.scss +98 -0
  524. package/src/scss/media/types/VCO.Media.Twitter.scss +87 -0
  525. package/src/scss/media/types/VCO.Media.Wikipedia.scss +65 -0
  526. package/src/scss/site/site.scss +748 -0
  527. package/src/scss/slider/VCO.Slide.scss +457 -0
  528. package/src/scss/slider/VCO.SlideNav.scss +332 -0
  529. package/src/scss/slider/VCO.StorySlider.scss +66 -0
  530. package/src/scss/snapmap/VCO.SnapMap.scss +103 -0
  531. package/src/scss/ui/VCO.Consent.scss +121 -0
  532. package/src/scss/ui/VCO.MenuBar.Button.scss +107 -0
  533. package/src/scss/ui/VCO.MenuBar.scss +20 -0
  534. package/src/scss/ui/VCO.Message.scss +101 -0
  535. package/src/site/site.ts +88 -0
  536. package/src/slider/Slide.ts +554 -0
  537. package/src/slider/SlideNav.ts +246 -0
  538. package/src/slider/StorySlider.ts +833 -0
  539. package/src/storymap/Consent.ts +471 -0
  540. package/src/storymap/StoryMap.ts +2118 -0
  541. package/src/storymap/content-state.ts +185 -0
  542. package/src/storymap/iiif.ts +1844 -0
  543. package/src/storymap/to-iiif.ts +921 -0
  544. package/src/storymap/validate.ts +257 -0
  545. package/src/types.ts +494 -0
  546. package/src/ui/MenuBar.ts +376 -0
  547. package/src/ui/Message.ts +127 -0
  548. package/src/ui/Swipable.ts +455 -0
  549. package/dist/assets/demo-CVQ7kFek.js +0 -1
  550. package/dist/assets/harness-C-VZV-ou.js +0 -1
  551. package/dist/assets/index-DDsPBPZA.js +0 -1
  552. package/dist/assets/main-DwbXrrYn.js +0 -17
@@ -0,0 +1,109 @@
1
+ import { Media } from "../Media";
2
+ import Dom from "../../dom/Dom";
3
+ import { sanitizeSlideText } from "../EmbedUtil";
4
+ import { loadJSONP, uniqueGlobalName } from "../../core/Load";
5
+
6
+ /* Media.Twitter
7
+ Produces Twitter Display
8
+ ================================================== */
9
+
10
+ export default class Twitter extends Media {
11
+ declare "user_id": string;
12
+ declare "media_id": string;
13
+
14
+ /* Load the media
15
+ ================================================== */
16
+ _loadMedia() {
17
+ // Loading Message
18
+ this.loadingMessage();
19
+
20
+ // Create Dom element
21
+ this._el.content_item = Dom.create("div", "vco-media-twitter", this._el.content);
22
+
23
+ // Get Media ID
24
+
25
+ const r = /(?:twitter\.com|x\.com)\/(.+?)\/status\/(\d+)/;
26
+ const match = r.exec(this._url());
27
+ if (match) {
28
+ this.user_id = match[1];
29
+ this.media_id = match[2];
30
+ } else {
31
+ throw new Error("Invalid Twitter URL");
32
+ }
33
+ const callbackName = uniqueGlobalName(`twitterCallback_${this.media_id}`);
34
+ const api_url = `https://api.twitter.com/1/statuses/oembed.json?id=${this.media_id}&include_entities=true&callback=${callbackName}`;
35
+ void this._fetchEmbed(api_url, callbackName);
36
+ }
37
+
38
+ async _fetchEmbed(api_url: string, callbackName: string) {
39
+ try {
40
+ this.createMedia(await loadJSONP<unknown>(api_url, callbackName));
41
+ } catch {
42
+ this.loadErrorDisplay("Unable to load this tweet.");
43
+ }
44
+ }
45
+
46
+ createMedia(d: unknown) {
47
+ const data = d as { html: string; author_url: string; author_name: string };
48
+ if (!data?.html) {
49
+ this.loadErrorDisplay("Unable to load this post.");
50
+ return;
51
+ }
52
+ // The oEmbed markup is positional: the date link follows the tweet text
53
+ // after a "&mdash;" separator. Every step below is optional so a markup
54
+ // change upstream degrades to a missing date/link rather than throwing.
55
+ const afterText = data.html.split("</p>&mdash;")[1] ?? "";
56
+ const tweetuser = data.author_url.split(/twitter\.com|x\.com\//)[1] ?? "";
57
+ const statusLink = afterText.split('<a href="')[1] ?? "";
58
+ const tweet_status_url = statusLink.split('">')[0] ?? "";
59
+ const tweet_status_date = (statusLink.split('">')[1] ?? "").split("</a>")[0] ?? "";
60
+
61
+ let tweet = "";
62
+ // TWEET CONTENT
63
+ let tweet_text = afterText ? data.html.split("</p>&mdash;")[0] + "</p></blockquote>" : "";
64
+ // Open links in new window
65
+ tweet_text = tweet_text.replace(/<a href/gi, '<a target="_blank" href');
66
+
67
+ // TWEET CONTENT
68
+ tweet += tweet_text;
69
+
70
+ // TWEET AUTHOR
71
+ tweet += "<div class='vcard'>";
72
+ tweet +=
73
+ "<a href='" +
74
+ tweet_status_url +
75
+ "' class='twitter-date' target='_blank'>" +
76
+ tweet_status_date +
77
+ "</a>";
78
+ tweet += "<div class='author'>";
79
+ tweet += "<a class='screen-name url' href='" + data.author_url + "' target='_blank'>";
80
+ tweet += "<span class='avatar'></span>";
81
+ tweet +=
82
+ "<span class='fn'>" +
83
+ data.author_name +
84
+ " <span class='vco-icon-twitter'></span></span>";
85
+ tweet +=
86
+ "<span class='nickname'>@" +
87
+ tweetuser +
88
+ "<span class='thumbnail-inline'></span></span>";
89
+ tweet += "</a>";
90
+ tweet += "</div>";
91
+ tweet += "</div>";
92
+
93
+ // Add to DOM
94
+ // The whole tweet is assembled from the oEmbed response's own HTML
95
+ // plus five string-concatenated fields, and that API does not escape
96
+ // HTML — so the result is untrusted third-party markup and goes
97
+ // through the sanitizer. It also repairs the four unguarded
98
+ // positional splits above: a markup change upstream now degrades to a
99
+ // missing date instead of throwing.
100
+ this._el.content_item?.appendChild(sanitizeSlideText(tweet));
101
+
102
+ // After Loaded
103
+ this.onLoaded();
104
+ }
105
+
106
+ updateMediaDisplay() {}
107
+
108
+ _updateMediaDisplay() {}
109
+ }
@@ -0,0 +1,14 @@
1
+ import { HtmlMediaBase, type HtmlMediaKind } from "./HtmlMedia";
2
+
3
+ /* Media.Video
4
+ A <video> element with a single <source> child.
5
+ ================================================== */
6
+
7
+ export default class Video extends HtmlMediaBase {
8
+ protected spec() {
9
+ return {
10
+ kind: "video" as HtmlMediaKind,
11
+ extensions: { mp4: "mp4", webm: "webm" },
12
+ };
13
+ }
14
+ }
@@ -0,0 +1,65 @@
1
+ import { vimeoId } from "../embedId";
2
+ import { Media } from "../Media";
3
+ import Dom from "../../dom/Dom";
4
+
5
+ /* Media.Vimeo
6
+ ================================================== */
7
+
8
+ export default class Vimeo extends Media {
9
+ declare "media_id": string;
10
+ declare "player": HTMLIFrameElement;
11
+
12
+ /* Load the media
13
+ ================================================== */
14
+ _loadMedia() {
15
+ // Loading Message
16
+ this.loadingMessage();
17
+
18
+ // Create Dom element
19
+ this._el.content_item = Dom.create(
20
+ "div",
21
+ "vco-media-item vco-media-iframe vco-media-vimeo vco-media-shadow",
22
+ this._el.content,
23
+ );
24
+
25
+ // Get Media ID
26
+ this.media_id = vimeoId(this._url()) ?? "";
27
+ if (!this.media_id) {
28
+ throw new Error("Invalid Vimeo URL");
29
+ }
30
+
31
+ // API URL — plain `&` separators. The HTML entity `&amp;` is correct
32
+ // inside markup but is not decoded in a URL property, so Vimeo was
33
+ // receiving params literally named `amp;byline` / `amp;color` and
34
+ // ignoring them.
35
+ const api_url =
36
+ "https://player.vimeo.com/video/" +
37
+ this.media_id +
38
+ "?api=1&title=0&byline=0&portrait=0&color=ffffff";
39
+
40
+ this.player = Dom.create("iframe", "", this._el.content_item) as HTMLIFrameElement;
41
+ this.player.width = "100%";
42
+ this.player.height = "100%";
43
+ this.player.frameBorder = "0";
44
+ this.player.src = api_url;
45
+
46
+ // After Loaded
47
+ this.onLoaded();
48
+ }
49
+
50
+ // Update Media Display
51
+ _updateMediaDisplay() {
52
+ this._sizeContentItemTo16x9();
53
+ }
54
+
55
+ _stopMedia() {
56
+ try {
57
+ this.player?.contentWindow?.postMessage(
58
+ JSON.stringify({ method: "pause" }),
59
+ "https://player.vimeo.com",
60
+ );
61
+ } catch (err) {
62
+ console.log(err);
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,46 @@
1
+ import { Media } from "../Media";
2
+ import Dom from "../../dom/Dom";
3
+ import { validateWebURL } from "../EmbedUtil";
4
+
5
+ /* Media.Website
6
+ An <iframe> pointed straight at a URL. Shared with the DocumentCloud
7
+ type, which is the same embed with a different CSS class.
8
+ ================================================= */
9
+
10
+ export class WebsiteBase extends Media {
11
+ declare "media_id": string;
12
+
13
+ /** Extra class on the wrapper element, e.g. "vco-media-documentcloud". */
14
+ protected extraClass(): string {
15
+ return "";
16
+ }
17
+
18
+ _loadMedia() {
19
+ this.loadingMessage();
20
+
21
+ const classes = `vco-media-item vco-media-iframe ${this.extraClass()}`.trim();
22
+ const content_item = Dom.create("div", classes, this._el.content);
23
+ this._el.content_item = content_item;
24
+
25
+ this.media_id = this._url();
26
+ // rebuilt from a validated src: injecting the raw URL as markup would
27
+ // allow stored XSS via the storymap JSON
28
+ const src = validateWebURL(this.media_id);
29
+ if (!src) {
30
+ this.loadErrorDisplay("Invalid URL.");
31
+ return;
32
+ }
33
+ const iframe = document.createElement("iframe");
34
+ iframe.setAttribute("src", src);
35
+ content_item.appendChild(iframe);
36
+ this.onLoaded();
37
+ }
38
+
39
+ _updateMediaDisplay() {
40
+ if (this._el.content_item) {
41
+ this._el.content_item.style.height = Number(this.options.height ?? 0) + "px";
42
+ }
43
+ }
44
+ }
45
+
46
+ export default class Website extends WebsiteBase {}
@@ -0,0 +1,134 @@
1
+ import { Media } from "../Media";
2
+ import Dom from "../../dom/Dom";
3
+ import { Language } from "../../language/Language";
4
+ import { getObjectAttributeByIndex } from "../../core/Util";
5
+ import { sanitizeSlideText } from "../EmbedUtil";
6
+ import { loadJSONP, uniqueGlobalName } from "../../core/Load";
7
+
8
+ /* Media.Wikipedia
9
+ ================================================== */
10
+
11
+ const CALLBACK_PREFIX = "wikipediaCallback_";
12
+ const MAX_ID_LENGTH = 512 - CALLBACK_PREFIX.length;
13
+
14
+ /**
15
+ * Split a Wikipedia article URL into its decoded title and language subdomain.
16
+ * Underscores and percent-encoding both decode to spaces; hash fragments are
17
+ * stripped. Falls back to the raw path segment when decoding fails.
18
+ */
19
+ export function parseWikipediaUrl(pageUrl: string): { title: string; language: string } {
20
+ const raw = pageUrl.split("wiki/")[1].split("#")[0];
21
+ const underscored = raw.replace(/_/g, " ");
22
+ let title: string;
23
+ try {
24
+ title = decodeURIComponent(underscored);
25
+ } catch {
26
+ title = underscored;
27
+ }
28
+ const language = pageUrl.split("//")[1].split(".wikipedia")[0];
29
+ return { title, language };
30
+ }
31
+
32
+ /** The deterministic part of the JSONP callback name for an article title. */
33
+ export function wikipediaCallbackBase(title: string): string {
34
+ return CALLBACK_PREFIX + title.replace(/[^0-9a-z]/gi, "").slice(0, MAX_ID_LENGTH);
35
+ }
36
+
37
+ /** The MediaWiki extracts API URL for a title, wrapping its answer in `callbackName`. */
38
+ export function wikipediaApiUrl(language: string, title: string, callbackName: string): string {
39
+ return `https://${language}.wikipedia.org/w/api.php?action=query&prop=extracts&redirects=&titles=${encodeURIComponent(title)}&exintro=1&format=json&callback=${callbackName}`;
40
+ }
41
+
42
+ export default class Wikipedia extends Media {
43
+ declare "media_id": string;
44
+
45
+ /* Load the media
46
+ ================================================== */
47
+ _loadMedia() {
48
+ // Loading Message
49
+ this.loadingMessage();
50
+
51
+ // Create Dom element
52
+ this._el.content_item = Dom.create(
53
+ "div",
54
+ "vco-media-item vco-media-wikipedia",
55
+ this._el.content,
56
+ );
57
+
58
+ // Get Media ID
59
+ const { title, language } = parseWikipediaUrl(this._url());
60
+ this.media_id = title;
61
+ // Claim a unique global slot: same-article concurrent loads must not
62
+ // share one (the loser's script would call a deleted global).
63
+ const callbackName = uniqueGlobalName(wikipediaCallbackBase(title));
64
+ const api_url = wikipediaApiUrl(language, title, callbackName);
65
+ void this._fetchExtract(api_url, callbackName);
66
+ }
67
+
68
+ async _fetchExtract(api_url: string, callbackName: string) {
69
+ try {
70
+ this.createMedia(await loadJSONP<unknown>(api_url, callbackName));
71
+ } catch {
72
+ this.loadErrorDisplay("Unable to load this article.");
73
+ }
74
+ }
75
+
76
+ createMedia(d: unknown) {
77
+ const data = d as { query?: unknown };
78
+ if (data.query) {
79
+ let content;
80
+ const wiki = {
81
+ entry: {} as Record<string, string>,
82
+ title: "",
83
+ text: "",
84
+ extract: "",
85
+ paragraphs: 1,
86
+ text_array: [] as string[],
87
+ };
88
+
89
+ const pages = data.query as { pages: Record<string, unknown> };
90
+ const first = getObjectAttributeByIndex(pages.pages, 0) as
91
+ Record<string, string> | undefined;
92
+ if (!first) {
93
+ this.loadErrorDisplay("Unable to load this article.");
94
+ return;
95
+ }
96
+ wiki.entry = first;
97
+ // a missing extract used to throw on the next line
98
+ wiki.extract = first.extract ?? "";
99
+ wiki.title = first.title ?? "";
100
+
101
+ if (wiki.extract.match("<p>")) {
102
+ wiki.text_array = wiki.extract.split("<p>");
103
+ } else {
104
+ wiki.text_array.push(wiki.extract);
105
+ }
106
+
107
+ for (let i = 0; i < wiki.text_array.length; i++) {
108
+ if (i + 1 <= wiki.paragraphs && i + 1 < wiki.text_array.length) {
109
+ wiki.text += "<p>" + wiki.text_array[i + 1];
110
+ }
111
+ }
112
+
113
+ content =
114
+ "<h4><a href='" + this._url() + "' target='_blank'>" + wiki.title + "</a></h4>";
115
+ content += "<span class='wiki-source'>" + Language.messages.wikipedia + "</span>";
116
+ content += wiki.text;
117
+
118
+ if (wiki.extract.match("REDIRECT")) {
119
+ // redirect page: leave content empty
120
+ } else {
121
+ // Add to DOM. `wiki.text` is MediaWiki API output and
122
+ // the media URL is storymap JSON, so the assembled markup is
123
+ // untrusted — it goes through the sanitizer.
124
+ this._el.content_item?.appendChild(sanitizeSlideText(content));
125
+ // After Loaded
126
+ this.onLoaded();
127
+ }
128
+ }
129
+ }
130
+
131
+ updateMediaDisplay() {}
132
+
133
+ _updateMediaDisplay() {}
134
+ }
@@ -0,0 +1,224 @@
1
+ import { unique_ID, clearTimer } from "../../core/Util";
2
+ import { youtubeId, queryParam } from "../embedId";
3
+ import { Media } from "../Media";
4
+ import Dom from "../../dom/Dom";
5
+
6
+ /* Media.YouTube
7
+ ================================================== */
8
+
9
+ /** How long to wait for the IFrame API script before giving up (one second apart). */
10
+ const YOUTUBE_API_ATTEMPTS = 10;
11
+
12
+ /* Minimal surface of the YouTube iframe API player used here. */
13
+ interface YTPlayer {
14
+ playVideo: () => void;
15
+ pauseVideo: () => void;
16
+ seekTo: (seconds: number) => void;
17
+ destroy: () => void;
18
+ loadVideoById: (id: string) => void;
19
+ cueVideoById: (id: string) => void;
20
+ setVolume: (volume: number) => void;
21
+ getDuration: () => number;
22
+ getPlayerState: () => number;
23
+ }
24
+
25
+ /* The externally loaded YT global, narrowed at its usage sites. */
26
+ type YTGlobal = {
27
+ Player: new (el: HTMLElement | string, opts: unknown) => YTPlayer;
28
+ PlayerState: Record<string, number>;
29
+ };
30
+
31
+ interface YouTubeMediaID {
32
+ id?: string;
33
+ start?: number | string;
34
+ hd?: boolean | string;
35
+ }
36
+
37
+ export default class YouTube extends Media {
38
+ declare "youtube_loaded": boolean;
39
+ declare "media_id": YouTubeMediaID;
40
+ declare "player": YTPlayer | null;
41
+ declare "_player_attempts": number;
42
+
43
+ /* Load the media
44
+ ================================================== */
45
+ async _loadMedia() {
46
+ // Loading Message
47
+ this.loadingMessage();
48
+
49
+ this.youtube_loaded = false;
50
+ this._player_attempts = 0;
51
+
52
+ // Create Dom element
53
+ this._el.content_item = Dom.create(
54
+ "div",
55
+ "vco-media-item vco-media-youtube vco-media-shadow",
56
+ this._el.content,
57
+ );
58
+ (this._el.content_item as HTMLElement).id = unique_ID(7);
59
+
60
+ // Get Media ID — the previous four-way branch chain missed /live/ and
61
+ // playlist links, and fell through to a console.log while still
62
+ // building a player with `id === undefined`
63
+ const id = youtubeId(this._url());
64
+ if (!id) {
65
+ throw new Error("Invalid YouTube URL");
66
+ }
67
+ this.media_id = { id: id };
68
+ this.media_id.start = queryParam(this._url(), "t") ?? undefined;
69
+ this.media_id.hd = queryParam(this._url(), "hd") ?? undefined;
70
+
71
+ // API Call
72
+ try {
73
+ await this.loadScript("https://www.youtube.com/iframe_api");
74
+ } catch {
75
+ // aborted or failed to load; nothing to show
76
+ return;
77
+ }
78
+ this.createMedia();
79
+ }
80
+
81
+ // Update Media Display
82
+ _updateMediaDisplay() {
83
+ this._sizeContentItemTo16x9();
84
+ }
85
+
86
+ _stopMedia() {
87
+ // cancel a pending API retry so a poll cannot outlive the slide
88
+ clearTimer(this.timer);
89
+ this.timer = null;
90
+ if (this.youtube_loaded && this.player) {
91
+ try {
92
+ const yt = YT as YTGlobal;
93
+ if (this.player.getPlayerState() === yt.PlayerState.PLAYING) {
94
+ this.player.pauseVideo();
95
+ }
96
+ } catch (err) {
97
+ console.log(err);
98
+ }
99
+ }
100
+ }
101
+
102
+ createMedia() {
103
+ // Determine Start of Media
104
+ if (typeof this.media_id.start != "undefined") {
105
+ const vidstart = this.media_id.start.toString();
106
+ // supports the "90" (seconds), "1m30s" and "1h2m30s" formats
107
+ const hours = /(\d+)h/.exec(vidstart);
108
+ const minutes = /(\d+)m/.exec(vidstart);
109
+ const seconds = /(\d+)s/.exec(vidstart);
110
+ if (hours || minutes || seconds) {
111
+ this.media_id.start =
112
+ (hours ? parseInt(hours[1], 10) * 3600 : 0) +
113
+ (minutes ? parseInt(minutes[1], 10) * 60 : 0) +
114
+ (seconds ? parseInt(seconds[1], 10) : 0);
115
+ } else {
116
+ const parsed = parseInt(vidstart, 10);
117
+ this.media_id.start = Number.isNaN(parsed) ? 0 : parsed;
118
+ }
119
+ } else {
120
+ this.media_id.start = 0;
121
+ }
122
+ // Determine HD
123
+ if (typeof this.media_id.hd != "undefined") {
124
+ this.media_id.hd = true;
125
+ } else {
126
+ this.media_id.hd = false;
127
+ }
128
+ this.createPlayer();
129
+ }
130
+
131
+ createPlayer() {
132
+ clearTimer(this.timer);
133
+ if (typeof YT != "undefined" && typeof YT.Player != "undefined") {
134
+ // Create Player
135
+ const yt = YT as YTGlobal;
136
+ const mount_id = this._el.content_item?.id;
137
+ if (!mount_id) {
138
+ return;
139
+ }
140
+ this.player = new yt.Player(mount_id, {
141
+ playerVars: {
142
+ enablejsapi: 1,
143
+ color: "white",
144
+ autohide: 1,
145
+ showinfo: 0,
146
+ theme: "light",
147
+ start: this.media_id.start,
148
+ fs: 0,
149
+ rel: 0,
150
+ },
151
+ videoId: this.media_id.id,
152
+ events: {
153
+ onReady: () => {
154
+ this.onPlayerReady();
155
+ },
156
+ onStateChange: this.onStateChange,
157
+ },
158
+ });
159
+ this.onLoaded();
160
+ } else {
161
+ // The IFrame API script has not arrived yet. Poll for it, but cap
162
+ // the attempts — an unbounded setTimeout recursion kept a timer
163
+ // alive forever on any network failure, and the loading message
164
+ // used to be dismissed by an unconditional onLoaded() below even
165
+ // though nothing was playing.
166
+ this._player_attempts = (this._player_attempts ?? 0) + 1;
167
+ if (this._player_attempts > YOUTUBE_API_ATTEMPTS) {
168
+ this.loadErrorDisplay("The YouTube player could not be loaded.");
169
+ return;
170
+ }
171
+ this.timer = setTimeout(() => {
172
+ this.createPlayer();
173
+ }, 1000);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Destroy the player, not just pause it: `stopMedia()` runs on every
179
+ * slide change, but teardown runs once and the iframe otherwise keeps
180
+ * the embedded video and its event listeners alive after disposal.
181
+ */
182
+ _disposeMedia() {
183
+ clearTimer(this.timer);
184
+ this.timer = null;
185
+ if (this.youtube_loaded) {
186
+ try {
187
+ this.player?.destroy?.();
188
+ } catch (err) {
189
+ console.log(err);
190
+ }
191
+ }
192
+ this.player = null;
193
+ this.youtube_loaded = false;
194
+ }
195
+
196
+ /* Events
197
+ ================================================== */
198
+ onPlayerReady(e?: unknown) {
199
+ this.youtube_loaded = true;
200
+ // The IFrame API replaces the placeholder div with its own iframe, so
201
+ // re-resolve the mount. Prefer the element this instance already
202
+ // holds: a document-wide getElementById() reads the global id space,
203
+ // which two viewers on a page both write into, and would hand this
204
+ // player the sibling's container. The id lookup stays as a fallback
205
+ // for the case where the node really was replaced under us.
206
+ if (!this._el.content_item?.isConnected) {
207
+ const mount_id = (this._el.content_item as HTMLElement | undefined)?.id;
208
+ const found = mount_id ? document.getElementById(mount_id) : null;
209
+ if (found) {
210
+ this._el.content_item = found;
211
+ }
212
+ }
213
+ this.onMediaLoaded();
214
+ this.onLoaded();
215
+ }
216
+
217
+ onStateChange(e: { data: number; target: YTPlayer }) {
218
+ const yt = YT as YTGlobal;
219
+ if (e.data === yt.PlayerState.ENDED) {
220
+ e.target.seekTo(0);
221
+ e.target.pauseVideo();
222
+ }
223
+ }
224
+ }