@projektemacher/storymapjs 0.10.7 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG +431 -19
- package/README.md +168 -17
- package/dist/assets/demo-bWnOyfUw.js +1 -0
- package/dist/assets/harness-C3JUv5Ii.js +1 -0
- package/dist/assets/harness-multi-XZNex3tb.js +1 -0
- package/dist/assets/harness-support-CjfZIVeb.js +1 -0
- package/dist/assets/index-wHPqGrBS.js +1 -0
- package/dist/assets/main-DQ32hWBM.js +17 -0
- package/dist/context.json +23 -9
- package/dist/css/fonts/files/amatic-sc-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/amatic-sc-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/amatic-sc-hebrew-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/amatic-sc-hebrew-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/amatic-sc-vietnamese-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/amatic-sc-vietnamese-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-100-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-100-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-200-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-200-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-600-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-600-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-800-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-800-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-900-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-100-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-100-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-200-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-200-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-600-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-600-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-800-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-800-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-900-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-100-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-100-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-200-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-200-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-600-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-600-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-800-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-800-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-900-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/bitter-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-200-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-600-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-800-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-arabic-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-200-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-600-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-800-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-200-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-600-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-800-normal.woff2 +0 -0
- package/dist/css/fonts/files/cairo-latin-ext-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/dancing-script-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-cyrillic-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-greek-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-greek-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-greek-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-greek-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-vietnamese-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/eb-garamond-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-greek-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-vietnamese-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/gentium-book-plus-vietnamese-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-vietnamese-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-vietnamese-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/old-standard-tt-vietnamese-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-cyrillic-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-greek-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-greek-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-greek-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-greek-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-hebrew-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-hebrew-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-vietnamese-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/open-sans-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-cyrillic-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-cyrillic-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-vietnamese-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-vietnamese-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-sc-vietnamese-900-normal.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-vietnamese-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/playfair-display-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-narrow-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-narrow-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-sans-narrow-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/pt-serif-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/raleway-cyrillic-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/raleway-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/raleway-cyrillic-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/raleway-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/raleway-vietnamese-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/raleway-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/roboto-slab-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/roboto-slab-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/roboto-slab-greek-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/roboto-slab-greek-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/roboto-slab-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-cyrillic-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-300-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-300-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-400-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-500-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-500-normal.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-700-italic.woff2 +0 -0
- package/dist/css/fonts/files/ubuntu-greek-ext-700-normal.woff2 +0 -0
- package/dist/css/fonts/files/unica-one-vietnamese-400-normal.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-cyrillic-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-cyrillic-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-greek-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-greek-wght-normal.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-vietnamese-wght-italic.woff2 +0 -0
- package/dist/css/fonts/files/vollkorn-vietnamese-wght-normal.woff2 +0 -0
- package/dist/css/fonts/font.abril-droidsans.css +3 -0
- package/dist/css/fonts/font.amatic-andika.css +57 -0
- package/dist/css/fonts/font.bitter-raleway.css +111 -0
- package/dist/css/fonts/font.cairo.css +312 -0
- package/dist/css/fonts/font.clicker-garamond.css +93 -0
- package/dist/css/fonts/font.dancing-ledger.css +12 -0
- package/dist/css/fonts/font.default.css +183 -0
- package/dist/css/fonts/font.fjalla-average.css +3 -0
- package/dist/css/fonts/font.georgia-helvetica.css +3 -0
- package/dist/css/fonts/font.knightlab.css +642 -0
- package/dist/css/fonts/font.lustria-lato.css +3 -0
- package/dist/css/fonts/font.medula-lato.css +3 -0
- package/dist/css/fonts/font.oldstandard.css +84 -0
- package/dist/css/fonts/font.opensans-gentiumbook.css +183 -0
- package/dist/css/fonts/font.playfair-faunaone.css +39 -0
- package/dist/css/fonts/font.playfair.css +147 -0
- package/dist/css/fonts/font.pt.css +183 -0
- package/dist/css/fonts/font.roboto-megrim.css +3 -0
- package/dist/css/fonts/font.rufina-sintony.css +3 -0
- package/dist/css/fonts/font.ubuntu.css +291 -0
- package/dist/css/fonts/font.unicaone-vollkorn.css +84 -0
- package/dist/css/storymap.css +1 -1
- package/dist/demo.html +3 -2
- package/dist/docs/api/.nojekyll +1 -0
- package/dist/docs/api/assets/custom.css +47 -0
- package/dist/docs/api/assets/hierarchy.js +1 -0
- package/dist/docs/api/assets/highlight.css +57 -0
- package/dist/docs/api/assets/icons.js +18 -0
- package/dist/docs/api/assets/icons.svg +1 -0
- package/dist/docs/api/assets/main.js +60 -0
- package/dist/docs/api/assets/navigation.js +1 -0
- package/dist/docs/api/assets/search.js +1 -0
- package/dist/docs/api/assets/style.css +1648 -0
- package/dist/docs/api/classes/StoryMap.html +2112 -0
- package/dist/docs/api/functions/MediaType.html +51 -0
- package/dist/docs/api/functions/isPresentation3Collection.html +47 -0
- package/dist/docs/api/functions/isPresentation3Manifest.html +53 -0
- package/dist/docs/api/functions/isSlideshowCollection.html +51 -0
- package/dist/docs/api/functions/loadCSS.html +63 -0
- package/dist/docs/api/functions/manifestToStorymapData.html +49 -0
- package/dist/docs/api/functions/setLanguage.html +54 -0
- package/dist/docs/api/functions/slideshowToStorymapData.html +51 -0
- package/dist/docs/api/functions/slideshowVersion.html +48 -0
- package/dist/docs/api/functions/storymapToManifest.html +57 -0
- package/dist/docs/api/functions/validateStorymap.html +53 -0
- package/dist/docs/api/functions/validateStorymapAndReport.html +54 -0
- package/dist/docs/api/hierarchy.html +28 -0
- package/dist/docs/api/index.html +300 -0
- package/dist/docs/api/interfaces/AnimationHandle.html +60 -0
- package/dist/docs/api/interfaces/ImagereadyPayload.html +71 -0
- package/dist/docs/api/interfaces/LanguageEntry.html +102 -0
- package/dist/docs/api/interfaces/LatLngLiteral.html +73 -0
- package/dist/docs/api/interfaces/LoadOptions.html +59 -0
- package/dist/docs/api/interfaces/MapEvents.html +116 -0
- package/dist/docs/api/interfaces/MapMarkerEvents.html +66 -0
- package/dist/docs/api/interfaces/MarkerEventPayload.html +57 -0
- package/dist/docs/api/interfaces/MediaEvents.html +78 -0
- package/dist/docs/api/interfaces/MenuBarEvents.html +114 -0
- package/dist/docs/api/interfaces/MessageEvents.html +72 -0
- package/dist/docs/api/interfaces/OlLayer.html +1400 -0
- package/dist/docs/api/interfaces/OlMap.html +1656 -0
- package/dist/docs/api/interfaces/OlProjection.html +332 -0
- package/dist/docs/api/interfaces/OlSource.html +784 -0
- package/dist/docs/api/interfaces/OlTileLayer.html +1497 -0
- package/dist/docs/api/interfaces/OlVectorLayer.html +1559 -0
- package/dist/docs/api/interfaces/OlView.html +1958 -0
- package/dist/docs/api/interfaces/SlideBackgroundState.html +66 -0
- package/dist/docs/api/interfaces/SlideEvents.html +78 -0
- package/dist/docs/api/interfaces/SlideNavEvents.html +72 -0
- package/dist/docs/api/interfaces/SlideshowPlayerSettings.html +182 -0
- package/dist/docs/api/interfaces/SlideshowToStorymapResult.html +60 -0
- package/dist/docs/api/interfaces/SlideshowTranslatorOptions.html +65 -0
- package/dist/docs/api/interfaces/SlideshowWarning.html +72 -0
- package/dist/docs/api/interfaces/StoryMapEvents.html +146 -0
- package/dist/docs/api/interfaces/StoryMapMarker.html +763 -0
- package/dist/docs/api/interfaces/StorySliderEvents.html +102 -0
- package/dist/docs/api/interfaces/StorymapBasemap.html +69 -0
- package/dist/docs/api/interfaces/StorymapData.html +77 -0
- package/dist/docs/api/interfaces/StorymapDataWrapper.html +60 -0
- package/dist/docs/api/interfaces/StorymapDocument.html +68 -0
- package/dist/docs/api/interfaces/StorymapError.html +63 -0
- package/dist/docs/api/interfaces/StorymapGeoreference.html +93 -0
- package/dist/docs/api/interfaces/StorymapGeoreferenceBody.html +74 -0
- package/dist/docs/api/interfaces/StorymapGroundControlPoint.html +69 -0
- package/dist/docs/api/interfaces/StorymapLanguageMap.html +57 -0
- package/dist/docs/api/interfaces/StorymapManifest.html +118 -0
- package/dist/docs/api/interfaces/StorymapManifestAnnotation.html +137 -0
- package/dist/docs/api/interfaces/StorymapManifestBackground.html +81 -0
- package/dist/docs/api/interfaces/StorymapManifestCanvas.html +188 -0
- package/dist/docs/api/interfaces/StorymapManifestContentResource.html +97 -0
- package/dist/docs/api/interfaces/StorymapManifestFeatureCollection.html +82 -0
- package/dist/docs/api/interfaces/StorymapManifestGeoreferencing.html +87 -0
- package/dist/docs/api/interfaces/StorymapManifestImageService.html +69 -0
- package/dist/docs/api/interfaces/StorymapManifestRange.html +75 -0
- package/dist/docs/api/interfaces/StorymapManifestService.html +77 -0
- package/dist/docs/api/interfaces/StorymapManifestSpecificResource.html +69 -0
- package/dist/docs/api/interfaces/StorymapManifestStatement.html +63 -0
- package/dist/docs/api/interfaces/StorymapMapOptions.html +92 -0
- package/dist/docs/api/interfaces/StorymapOptions.html +734 -0
- package/dist/docs/api/interfaces/StorymapOverlayLayer.html +157 -0
- package/dist/docs/api/interfaces/StorymapSlide.html +186 -0
- package/dist/docs/api/interfaces/StorymapSlideBackground.html +72 -0
- package/dist/docs/api/interfaces/StorymapSlideLocation.html +161 -0
- package/dist/docs/api/interfaces/StorymapSlideMarker.html +103 -0
- package/dist/docs/api/interfaces/StorymapSlideMedia.html +149 -0
- package/dist/docs/api/interfaces/StorymapSlideNarration.html +117 -0
- package/dist/docs/api/interfaces/StorymapSlideText.html +72 -0
- package/dist/docs/api/interfaces/StorymapTilejson.html +105 -0
- package/dist/docs/api/interfaces/SwipableEvents.html +102 -0
- package/dist/docs/api/interfaces/TextEvents.html +66 -0
- package/dist/docs/api/media/es.json +31 -0
- package/dist/docs/api/media/events.md +66 -0
- package/dist/docs/api/media/migration-from-knightlab.md +399 -0
- package/dist/docs/api/media/slideshow.md +109 -0
- package/dist/docs/api/media/storymap-as-iiif-manifest.md +1007 -0
- package/dist/docs/api/modules.html +50 -0
- package/dist/docs/api/types/ContentState.html +70 -0
- package/dist/docs/api/types/FiredEvent.html +43 -0
- package/dist/docs/api/types/ImagereadyKind.html +34 -0
- package/dist/docs/api/types/MediaTypeMatch.html +78 -0
- package/dist/docs/api/types/SwipeDirection.html +36 -0
- package/dist/docs/api/types/TileSourceFactory.html +53 -0
- package/dist/docs/authoring.html +306 -0
- package/dist/docs/events.html +263 -0
- package/dist/docs/iiif.html +738 -69
- package/dist/docs/migration.html +360 -11
- package/dist/docs/readme.html +149 -17
- package/dist/embed/index.html +8 -1
- package/dist/examples/font-css-false.json +33 -0
- package/dist/examples/issue-242-nonlatin.json +55 -0
- package/dist/examples/issue-305-start-at-slide-data.json +96 -0
- package/dist/examples/issue-358-iframe.json +57 -0
- package/dist/examples/issue-iiif-geo.json +32 -0
- package/dist/examples/issue-image-alt.json +23 -0
- package/dist/examples/issue-image-region.json +42 -0
- package/dist/examples/issue-image-srcset.json +24 -0
- package/dist/examples/layers-control.json +60 -0
- package/dist/examples/map-area-overlays.json +68 -0
- package/dist/examples/map-template-provider.json +36 -0
- package/dist/examples/multi-media.json +71 -0
- package/dist/examples/no-map.json +44 -0
- package/dist/examples-iiif/annotated-image.json +204 -0
- package/dist/examples-iiif/bob-boilen.json +11 -5
- package/dist/examples-iiif/courbet.json +9 -6
- package/dist/examples-iiif/empty.json +8 -4
- package/dist/examples-iiif/flickr-drewvigal.json +248 -24
- package/dist/examples-iiif/flickr-zach.wise.json +8 -4
- package/dist/examples-iiif/font-css-false.json +114 -0
- package/dist/examples-iiif/georeferenced-layer-unsupported.json +153 -0
- package/dist/examples-iiif/georeferenced-layer.json +318 -0
- package/dist/examples-iiif/iiif-wellcome.json +9 -6
- package/dist/examples-iiif/instagram-chenpamela.json +381 -36
- package/dist/examples-iiif/instagram_brentfoster.json +429 -40
- package/dist/examples-iiif/instagram_couch.json +261 -26
- package/dist/examples-iiif/instagram_joegermuska.json +441 -41
- package/dist/examples-iiif/instagram_matteich.json +261 -26
- package/dist/examples-iiif/instagram_mirandamulligan.json +261 -26
- package/dist/examples-iiif/instagram_raymondmccrea.json +261 -26
- package/dist/examples-iiif/instagram_test.json +261 -26
- package/dist/examples-iiif/issue-134-no-lines.json +9 -5
- package/dist/examples-iiif/issue-177-color-vars.json +9 -5
- package/dist/examples-iiif/issue-211-rtl.json +9 -5
- package/dist/examples-iiif/issue-242-nonlatin.json +239 -0
- package/dist/examples-iiif/issue-272-facebook.json +9 -5
- package/dist/examples-iiif/issue-305-start-at-slide-data.json +305 -0
- package/dist/examples-iiif/issue-305-start-at-slide.json +9 -5
- package/dist/examples-iiif/issue-341-distance.json +9 -5
- package/dist/examples-iiif/issue-358-iframe.json +190 -0
- package/dist/examples-iiif/issue-360-juxtapose.json +22 -7
- package/dist/examples-iiif/issue-368-null-fields.json +9 -5
- package/dist/examples-iiif/issue-375-code-lists.json +9 -5
- package/dist/examples-iiif/issue-381-dateline.json +9 -5
- package/dist/examples-iiif/issue-405-custom-icon.json +203 -0
- package/dist/examples-iiif/issue-425-many-slides.json +9 -5
- package/dist/examples-iiif/issue-428-background.json +20 -8
- package/dist/examples-iiif/issue-435-googlemaps.json +9 -5
- package/dist/examples-iiif/issue-437-documentcloud.json +22 -7
- package/dist/examples-iiif/issue-451-webp.json +9 -5
- package/dist/examples-iiif/issue-455-audio.json +9 -5
- package/dist/examples-iiif/issue-480-shorts.json +9 -5
- package/dist/examples-iiif/issue-506-marker-sync.json +9 -5
- package/dist/examples-iiif/issue-iiif-geo.json +200 -0
- package/dist/examples-iiif/issue-image-alt.json +90 -0
- package/dist/examples-iiif/issue-image-region.json +203 -0
- package/dist/examples-iiif/issue-image-srcset.json +87 -0
- package/dist/examples-iiif/jansteen.json +9 -6
- package/dist/examples-iiif/katrina.json +197 -41
- package/dist/examples-iiif/layers-control.json +226 -0
- package/dist/examples-iiif/map-area-overlays.json +289 -0
- package/dist/examples-iiif/map-template-provider.json +133 -0
- package/dist/examples-iiif/marktwain.json +255 -58
- package/dist/examples-iiif/multi-media.json +237 -0
- package/dist/examples-iiif/no-map.json +148 -0
- package/dist/examples-iiif/population.json +440 -76
- package/dist/examples-iiif/president.json +456 -83
- package/dist/examples-iiif/scroll-hint.json +190 -0
- package/dist/examples-iiif/seurat.json +113 -22
- package/dist/examples-iiif/zoomify-clamp.json +153 -0
- package/dist/examples-slideshow/single.json +79 -0
- package/dist/examples-slideshow/static/pixel.png +0 -0
- package/dist/examples-slideshow/static.json +44 -0
- package/dist/harness-multi.html +17 -0
- package/dist/harness.html +4 -2
- package/dist/index.html +19 -12
- package/dist/js/storymap.d.ts +2669 -307
- package/dist/js/storymap.js +10820 -6196
- package/dist/js/storymap.js.map +1 -1
- package/dist/navplace-properties.json +54 -0
- package/dist/site.css +54 -36
- package/docs/migration-from-knightlab.md +279 -19
- package/docs/storymap-as-iiif-manifest.md +633 -136
- package/package.json +12 -7
- package/schema/storymap.schema.json +733 -80
- package/src/animation/easings.ts +8 -1
- package/src/animation/tween.ts +186 -0
- package/src/core/Browser.ts +6 -5
- package/src/core/Load.ts +54 -2
- package/src/core/Util.ts +257 -193
- package/src/core/mixins.ts +66 -35
- package/src/core/viewers.ts +94 -0
- package/src/dom/DomEvent.ts +27 -8
- package/src/globals.d.ts +8 -0
- package/src/language/Language.ts +206 -25
- package/src/language/locale/.expected-gaps.json +346 -0
- package/src/language/locale/be.json +15 -2
- package/src/language/locale/bg.json +15 -2
- package/src/language/locale/cs.json +15 -2
- package/src/language/locale/de.json +23 -2
- package/src/language/locale/el.json +15 -2
- package/src/language/locale/en.json +17 -3
- package/src/language/locale/es.json +15 -2
- package/src/language/locale/et.json +5 -1
- package/src/language/locale/fr.json +15 -2
- package/src/language/locale/he.json +16 -3
- package/src/language/locale/hu.json +15 -2
- package/src/language/locale/is.json +5 -1
- package/src/language/locale/it.json +15 -2
- package/src/language/locale/jp.json +15 -2
- package/src/language/locale/ko.json +15 -2
- package/src/language/locale/nl.json +15 -2
- package/src/language/locale/nn.json +5 -1
- package/src/language/locale/no.json +15 -2
- package/src/language/locale/pl.json +15 -2
- package/src/language/locale/pt.json +15 -2
- package/src/language/locale/ru.json +15 -2
- package/src/language/locale/sk.json +15 -2
- package/src/language/locale/sr.json +5 -1
- package/src/language/locale/sv.json +15 -2
- package/src/language/locale/tr.json +15 -2
- package/src/language/locale/uk.json +15 -2
- package/src/language/locale/ur.json +5 -1
- package/src/language/locale/zh-cn.json +15 -2
- package/src/language/locale/zh-tw.json +15 -2
- package/src/main.ts +143 -0
- package/src/map/Map.ts +227 -112
- package/src/map/MapMarker.ts +44 -8
- package/src/map/georeference.ts +325 -0
- package/src/map/openlayers/Map.OpenLayers.ts +1601 -263
- package/src/map/openlayers/MapMarker.OpenLayers.ts +348 -24
- package/src/map/openlayers/zoomifyTiles.ts +1 -4
- package/src/map/slideView.ts +149 -0
- package/src/map/types.ts +2 -0
- package/src/media/EmbedUtil.ts +333 -24
- package/src/media/Media.ts +270 -59
- package/src/media/embedId.ts +110 -0
- package/src/media/types/Audio.ts +9 -82
- package/src/media/types/Blockquote.ts +2 -3
- package/src/media/types/DailyMotion.ts +5 -10
- package/src/media/types/DocumentCloud.ts +6 -35
- package/src/media/types/Facebook.ts +3 -4
- package/src/media/types/Flickr.ts +23 -12
- package/src/media/types/GoogleDoc.ts +3 -4
- package/src/media/types/HtmlMedia.ts +233 -0
- package/src/media/types/IFrame.ts +3 -4
- package/src/media/types/Image.ts +87 -9
- package/src/media/types/Juxtapose.ts +14 -5
- package/src/media/types/SoundCloud.ts +28 -6
- package/src/media/types/Text.ts +46 -21
- package/src/media/types/Twitter.ts +35 -20
- package/src/media/types/Video.ts +9 -79
- package/src/media/types/Vimeo.ts +11 -11
- package/src/media/types/Website.ts +23 -13
- package/src/media/types/Wikipedia.ts +18 -8
- package/src/media/types/YouTube.ts +72 -40
- package/src/scss/Typography.scss +16 -18
- package/src/scss/VCO.StoryMap.scss +208 -12
- package/src/scss/Variables.scss +3 -2
- package/src/scss/core/Mixins.scss +5 -63
- package/src/scss/core/Reset.scss +5 -18
- package/src/scss/fonts/font.amatic-andika.scss +3 -0
- package/src/scss/fonts/font.bitter-raleway.scss +6 -0
- package/src/scss/fonts/font.cairo.scss +79 -0
- package/src/scss/fonts/font.clicker-garamond.scss +5 -0
- package/src/scss/fonts/font.dancing-ledger.scss +1 -0
- package/src/scss/fonts/font.knightlab.scss +14 -0
- package/src/scss/fonts/font.oldstandard.scss +6 -0
- package/src/scss/fonts/font.opensans-gentiumbook.scss +5 -0
- package/src/scss/fonts/font.playfair-faunaone.scss +2 -0
- package/src/scss/fonts/font.playfair.scss +4 -0
- package/src/scss/fonts/font.pt.scss +6 -0
- package/src/scss/fonts/font.ubuntu.scss +4 -0
- package/src/scss/fonts/font.unicaone-vollkorn.scss +5 -0
- package/src/scss/map/VCO.Map.scss +1 -1
- package/src/scss/map/VCO.MapMarker.scss +114 -8
- package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +7 -4
- package/src/scss/media/VCO.Media.scss +14 -17
- package/src/scss/media/types/VCO.Media.Blockquote.scss +1 -1
- package/src/scss/media/types/VCO.Media.Text.scss +13 -5
- package/src/scss/media/types/VCO.Media.Twitter.scss +4 -4
- package/src/scss/media/types/VCO.Media.Wikipedia.scss +3 -19
- package/src/scss/site/site.scss +55 -36
- package/src/scss/slider/VCO.Slide.scss +61 -13
- package/src/scss/slider/VCO.SlideNav.scss +34 -24
- package/src/scss/slider/VCO.StorySlider.scss +53 -1
- package/src/scss/snapmap/VCO.SnapMap.scss +3 -3
- package/src/scss/ui/VCO.Consent.scss +63 -13
- package/src/scss/ui/VCO.Layers.scss +119 -0
- package/src/scss/ui/VCO.MenuBar.Button.scss +143 -14
- package/src/scss/ui/VCO.MenuBar.scss +9 -2
- package/src/scss/ui/VCO.Message.scss +16 -5
- package/src/site/site.ts +2 -1
- package/src/slider/Slide.ts +326 -74
- package/src/slider/SlideNav.ts +54 -9
- package/src/slider/StorySlider.ts +352 -60
- package/src/storymap/Consent.ts +429 -82
- package/src/storymap/StoryMap.ts +2163 -340
- package/src/storymap/content-state.ts +180 -0
- package/src/storymap/font-css.ts +72 -0
- package/src/storymap/from-slideshow.ts +785 -0
- package/src/storymap/iiif-shared.ts +228 -0
- package/src/storymap/iiif.ts +1742 -95
- package/src/storymap/to-iiif.ts +1008 -0
- package/src/storymap/validate.ts +80 -7
- package/src/types.ts +591 -29
- package/src/ui/LayersControl.ts +302 -0
- package/src/ui/MenuBar.ts +325 -61
- package/src/ui/Message.ts +44 -2
- package/src/ui/Swipable.ts +170 -85
- package/dist/assets/demo-D6cTmzn6.js +0 -1
- package/dist/assets/harness-BPFlzutp.js +0 -1
- package/dist/assets/index-DDsPBPZA.js +0 -1
- package/dist/assets/main-Y-MYUSJ4.js +0 -17
- package/src/animation/morpheus.d.ts +0 -41
- package/src/scss/VCO.StoryMap.Dark.scss +0 -138
- package/src/scss/Variables.Dark.scss +0 -56
- package/src/scss/media/types/VCO.Media.Instagram.scss +0 -7
- package/src/scss/media/types/VCO.Media.Profile.scss +0 -5
- package/src/ui/Draggable.ts +0 -374
package/src/media/types/Image.ts
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import { Media } from "../Media";
|
|
2
2
|
import Dom from "../../dom/Dom";
|
|
3
|
-
import {
|
|
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.
|
|
@@ -8,18 +33,24 @@ import { Language } from "../../language/Language";
|
|
|
8
33
|
================================================== */
|
|
9
34
|
|
|
10
35
|
export default class Image extends Media {
|
|
36
|
+
/** The `load` handler on the image, stored so dispose() can detach it. */
|
|
37
|
+
declare "_onLoad": (() => void) | null;
|
|
38
|
+
|
|
11
39
|
/* Load the media
|
|
12
40
|
================================================== */
|
|
13
41
|
_loadMedia() {
|
|
14
42
|
// Loading Message
|
|
15
|
-
this.
|
|
43
|
+
this.loadingMessage();
|
|
16
44
|
|
|
17
|
-
// Link
|
|
18
|
-
|
|
45
|
+
// Link — protocol-checked: a `javascript:` href in the storymap JSON
|
|
46
|
+
// would be a click-through XSS (see Media._initLayout)
|
|
47
|
+
const link_href = this.data.link ? validateWebURL(this.data.link) : null;
|
|
48
|
+
if (link_href) {
|
|
19
49
|
this._el.content_link = Dom.create("a", "", this._el.content);
|
|
20
50
|
const content_link = this._el.content_link as HTMLAnchorElement;
|
|
21
|
-
content_link.href =
|
|
51
|
+
content_link.href = link_href;
|
|
22
52
|
content_link.target = "_blank";
|
|
53
|
+
content_link.rel = "noopener noreferrer";
|
|
23
54
|
this._el.content_item = Dom.create(
|
|
24
55
|
"img",
|
|
25
56
|
"vco-media-item vco-media-image vco-media-shadow",
|
|
@@ -33,17 +64,64 @@ export default class Image extends Media {
|
|
|
33
64
|
);
|
|
34
65
|
}
|
|
35
66
|
|
|
36
|
-
// Media Loaded Event
|
|
37
|
-
|
|
67
|
+
// Media Loaded Event. The reference is kept so dispose() can detach
|
|
68
|
+
// it: an inline arrow function has no other handle.
|
|
69
|
+
this._onLoad = () => {
|
|
38
70
|
this.onMediaLoaded();
|
|
39
|
-
}
|
|
71
|
+
};
|
|
72
|
+
this._el.content_item.addEventListener("load", this._onLoad);
|
|
40
73
|
|
|
41
|
-
|
|
74
|
+
const img = this._el.content_item as HTMLImageElement;
|
|
75
|
+
// offscreen/preloaded slides stay lazy (the active slide is
|
|
76
|
+
// upgraded to eager on activation, see Slide.setActive); decoding
|
|
77
|
+
// is only a hint — old browsers ignore both attributes
|
|
78
|
+
img.decoding = "async";
|
|
79
|
+
img.loading = this._state.eager ? "eager" : "lazy";
|
|
80
|
+
// responsive sizes (perf): IIIF image URLs request a container-
|
|
81
|
+
// matched width; author-provided srcset/sizes pass through;
|
|
82
|
+
// everything else renders byte-identically
|
|
83
|
+
const media_width = Number(this.options.width) || 0;
|
|
84
|
+
const sized = iiifSizedUrl(this._url(), media_width);
|
|
85
|
+
img.src = sized ?? this._url();
|
|
86
|
+
// accessibility: explicit alt text, falling back to the caption as
|
|
87
|
+
// plain text; an empty string marks a decorative image
|
|
88
|
+
img.alt = this._altText();
|
|
89
|
+
if (this.data.srcset) {
|
|
90
|
+
img.srcset = this.data.srcset as string;
|
|
91
|
+
}
|
|
92
|
+
if (this.data.sizes) {
|
|
93
|
+
img.sizes = this.data.sizes as string;
|
|
94
|
+
}
|
|
42
95
|
|
|
96
|
+
// the element is built and the src is set: hand over to Media so the
|
|
97
|
+
// loading overlay is hidden and credit/caption are rendered. The
|
|
98
|
+
// `load` listener above only fires the separate media_loaded event.
|
|
43
99
|
this.onLoaded();
|
|
44
100
|
}
|
|
45
101
|
|
|
102
|
+
_altText(): string {
|
|
103
|
+
const alt = this.data.alt as string | undefined;
|
|
104
|
+
if (alt !== undefined && alt !== "") {
|
|
105
|
+
return alt;
|
|
106
|
+
}
|
|
107
|
+
const caption = this.data.caption as string | null | undefined;
|
|
108
|
+
if (caption) {
|
|
109
|
+
return caption
|
|
110
|
+
.replace(/<[^>]*>/g, " ")
|
|
111
|
+
.replace(/\s+/g, " ")
|
|
112
|
+
.trim();
|
|
113
|
+
}
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
|
|
46
117
|
_updateMediaDisplay(layout?: string) {
|
|
47
118
|
// modern browsers size media correctly without engine-specific fixes
|
|
48
119
|
}
|
|
120
|
+
|
|
121
|
+
_disposeMedia(): void {
|
|
122
|
+
if (this._onLoad) {
|
|
123
|
+
this._el.content_item?.removeEventListener("load", this._onLoad);
|
|
124
|
+
this._onLoad = null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
49
127
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Media } from "../Media";
|
|
2
2
|
import Dom from "../../dom/Dom";
|
|
3
|
-
import {
|
|
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.
|
|
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
|
-
//
|
|
24
|
-
|
|
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.
|
|
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 {
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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(
|
|
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.warn("StoryMapJS: error unbinding SoundCloud widget.", err);
|
|
95
|
+
}
|
|
96
|
+
this.widget = null;
|
|
97
|
+
this.soundCloudCreated = false;
|
|
98
|
+
}
|
|
77
99
|
}
|
package/src/media/types/Text.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { mergeData,
|
|
1
|
+
import { mergeData, htmlify, convertUnixTime } from "../../core/Util";
|
|
2
2
|
import { Evented, type EventedInstance } from "../../core/mixins";
|
|
3
3
|
import Dom from "../../dom/Dom";
|
|
4
|
+
import { sanitizeSlideText } from "../EmbedUtil";
|
|
4
5
|
|
|
5
6
|
interface TextData {
|
|
6
7
|
uniqueid?: string | null;
|
|
@@ -13,13 +14,21 @@ interface TextData {
|
|
|
13
14
|
interface TextOptions {
|
|
14
15
|
title?: boolean;
|
|
15
16
|
text_align?: string;
|
|
17
|
+
/** BCP 47 tag for the slide text (from `StorymapSlide.language`). */
|
|
18
|
+
language?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface TextEvents {
|
|
22
|
+
loaded: TextData;
|
|
23
|
+
added: TextData;
|
|
24
|
+
removed: TextData;
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
class TextBase {
|
|
19
28
|
declare "_el": Record<string, HTMLElement>;
|
|
20
29
|
declare "data": TextData;
|
|
21
30
|
declare "options": TextOptions;
|
|
22
|
-
declare "fire": EventedInstance["fire"];
|
|
31
|
+
declare "fire": EventedInstance<TextEvents>["fire"];
|
|
23
32
|
|
|
24
33
|
/* Constructor
|
|
25
34
|
================================================== */
|
|
@@ -34,11 +43,14 @@ class TextBase {
|
|
|
34
43
|
start_btn: {} as HTMLElement,
|
|
35
44
|
};
|
|
36
45
|
|
|
37
|
-
// Data
|
|
46
|
+
// Data. The placeholders were the literal strings "headline" and
|
|
47
|
+
// "text", which mergeData only overwrites when the key is present — so
|
|
48
|
+
// a slide with body text and no headline rendered an <h2>headline</h2>.
|
|
49
|
+
// The renderer guards both on `!== ""`, so empty is the real default.
|
|
38
50
|
this.data = {
|
|
39
51
|
uniqueid: "",
|
|
40
|
-
headline: "
|
|
41
|
-
text: "
|
|
52
|
+
headline: "",
|
|
53
|
+
text: "",
|
|
42
54
|
};
|
|
43
55
|
|
|
44
56
|
// Options
|
|
@@ -46,13 +58,22 @@ class TextBase {
|
|
|
46
58
|
title: false,
|
|
47
59
|
};
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
mergeData(this.data, data);
|
|
50
62
|
|
|
51
63
|
// Merge Options
|
|
52
64
|
mergeData(this.options, options);
|
|
53
65
|
|
|
54
66
|
this._el.container = Dom.create("div", "vco-text");
|
|
55
|
-
this._el.container.id = this.data.uniqueid;
|
|
67
|
+
this._el.container.id = this.data.uniqueid ?? "";
|
|
68
|
+
// Pronounce mixed-language slides correctly: the reader reports
|
|
69
|
+
// which language map it picked, and the DOM should say so too.
|
|
70
|
+
if (
|
|
71
|
+
typeof this.options.language === "string" &&
|
|
72
|
+
this.options.language !== "" &&
|
|
73
|
+
this.options.language !== "none"
|
|
74
|
+
) {
|
|
75
|
+
this._el.container.setAttribute("lang", this.options.language);
|
|
76
|
+
}
|
|
56
77
|
|
|
57
78
|
this._initLayout();
|
|
58
79
|
|
|
@@ -120,27 +141,31 @@ class TextBase {
|
|
|
120
141
|
this._el.content_container.classList.add("vco-text-align-" + align);
|
|
121
142
|
}
|
|
122
143
|
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.addDateText(convertUnixTime(this.data.date.created_time));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Headline
|
|
130
|
-
if (this.data.headline !== "") {
|
|
144
|
+
// Headline (sanitized; issue #358 keeps formatting but drops scripts)
|
|
145
|
+
const headline = this.data.headline ?? "";
|
|
146
|
+
if (headline !== "") {
|
|
131
147
|
let headline_class = "vco-headline";
|
|
132
148
|
if (this.options.title) {
|
|
133
149
|
headline_class = "vco-headline vco-headline-title";
|
|
134
150
|
}
|
|
135
151
|
this._el.headline = Dom.create("h2", headline_class, this._el.content_container);
|
|
136
|
-
this._el.headline.
|
|
152
|
+
this._el.headline.appendChild(sanitizeSlideText(headline));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Date (only rendered when the slide has one; issue #286). Emitted
|
|
156
|
+
// after the headline and as a <p> (issue #385 wave): an <h3> before
|
|
157
|
+
// the <h2> was a heading-order skip
|
|
158
|
+
if (this.data.date && this.data.date.created_time && this.data.date.created_time !== "") {
|
|
159
|
+
this._el.date = Dom.create("p", "vco-headline-date", this._el.content_container);
|
|
160
|
+
this.addDateText(convertUnixTime(this.data.date.created_time));
|
|
137
161
|
}
|
|
138
162
|
|
|
139
|
-
// Text
|
|
140
|
-
|
|
163
|
+
// Text (sanitized; issue #358 allows extra iframe media in the text field)
|
|
164
|
+
const text = this.data.text ?? "";
|
|
165
|
+
if (text !== "") {
|
|
141
166
|
let text_content = "";
|
|
142
167
|
|
|
143
|
-
text_content += htmlify(
|
|
168
|
+
text_content += htmlify(text);
|
|
144
169
|
|
|
145
170
|
// Date
|
|
146
171
|
if (
|
|
@@ -157,7 +182,7 @@ class TextBase {
|
|
|
157
182
|
}
|
|
158
183
|
|
|
159
184
|
this._el.content = Dom.create("div", "vco-text-content", this._el.content_container);
|
|
160
|
-
this._el.content.
|
|
185
|
+
this._el.content.appendChild(sanitizeSlideText(text_content));
|
|
161
186
|
}
|
|
162
187
|
|
|
163
188
|
// Fire event that the slide is loaded
|
|
@@ -165,7 +190,7 @@ class TextBase {
|
|
|
165
190
|
}
|
|
166
191
|
}
|
|
167
192
|
|
|
168
|
-
export default class Text extends Evented(TextBase) {
|
|
193
|
+
export default class Text extends Evented<TextEvents, typeof TextBase>(TextBase) {
|
|
169
194
|
constructor(...args: ConstructorParameters<typeof TextBase>) {
|
|
170
195
|
super(...args);
|
|
171
196
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Media } from "../Media";
|
|
2
2
|
import Dom from "../../dom/Dom";
|
|
3
|
-
import {
|
|
3
|
+
import { sanitizeSlideText } from "../EmbedUtil";
|
|
4
|
+
import { tweetAuthor, tweetId } from "../embedId";
|
|
4
5
|
import { loadJSONP, uniqueGlobalName } from "../../core/Load";
|
|
5
6
|
|
|
6
7
|
/* Media.Twitter
|
|
@@ -15,18 +16,21 @@ export default class Twitter extends Media {
|
|
|
15
16
|
================================================== */
|
|
16
17
|
_loadMedia() {
|
|
17
18
|
// Loading Message
|
|
18
|
-
this.
|
|
19
|
+
this.loadingMessage();
|
|
19
20
|
|
|
20
21
|
// Create Dom element
|
|
21
22
|
this._el.content_item = Dom.create("div", "vco-media-twitter", this._el.content);
|
|
22
23
|
|
|
23
|
-
// Get Media ID
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.
|
|
24
|
+
// Get Media ID — routed here by MediaType, extracted by the shared
|
|
25
|
+
// helpers so the accepted shapes cannot diverge again. The id stays
|
|
26
|
+
// numeric-only, as before: anything else is not a status URL.
|
|
27
|
+
const media_id = tweetId(this._url());
|
|
28
|
+
const user_id = tweetAuthor(this._url());
|
|
29
|
+
if (media_id && user_id && /^\d+$/.test(media_id)) {
|
|
30
|
+
this.user_id = user_id;
|
|
31
|
+
this.media_id = media_id;
|
|
32
|
+
} else {
|
|
33
|
+
throw new Error("Invalid Twitter URL");
|
|
30
34
|
}
|
|
31
35
|
const callbackName = uniqueGlobalName(`twitterCallback_${this.media_id}`);
|
|
32
36
|
const api_url = `https://api.twitter.com/1/statuses/oembed.json?id=${this.media_id}&include_entities=true&callback=${callbackName}`;
|
|
@@ -43,17 +47,22 @@ export default class Twitter extends Media {
|
|
|
43
47
|
|
|
44
48
|
createMedia(d: unknown) {
|
|
45
49
|
const data = d as { html: string; author_url: string; author_name: string };
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
if (!data?.html) {
|
|
51
|
+
this.loadErrorDisplay("Unable to load this post.");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// The oEmbed markup is positional: the date link follows the tweet text
|
|
55
|
+
// after a "—" separator. Every step below is optional so a markup
|
|
56
|
+
// change upstream degrades to a missing date/link rather than throwing.
|
|
57
|
+
const afterText = data.html.split("</p>—")[1] ?? "";
|
|
58
|
+
const tweetuser = data.author_url.split(/twitter\.com|x\.com\//)[1] ?? "";
|
|
59
|
+
const statusLink = afterText.split('<a href="')[1] ?? "";
|
|
60
|
+
const tweet_status_url = statusLink.split('">')[0] ?? "";
|
|
61
|
+
const tweet_status_date = (statusLink.split('">')[1] ?? "").split("</a>")[0] ?? "";
|
|
62
|
+
|
|
63
|
+
let tweet = "";
|
|
49
64
|
// TWEET CONTENT
|
|
50
|
-
tweet_text = data.html.split("</p>—")[0] + "</p></blockquote>";
|
|
51
|
-
// the oembed endpoint returns x.com URLs since the rebrand — parse both
|
|
52
|
-
const tweetuser = data.author_url.split(/twitter\.com|x\.com\//)[1];
|
|
53
|
-
const tweet_status_temp = data.html.split("</p>—")[1].split('<a href="')[1];
|
|
54
|
-
const tweet_status_url = tweet_status_temp.split('">')[0];
|
|
55
|
-
const tweet_status_date = tweet_status_temp.split('">')[1].split("</a>")[0];
|
|
56
|
-
|
|
65
|
+
let tweet_text = afterText ? data.html.split("</p>—")[0] + "</p></blockquote>" : "";
|
|
57
66
|
// Open links in new window
|
|
58
67
|
tweet_text = tweet_text.replace(/<a href/gi, '<a target="_blank" href');
|
|
59
68
|
|
|
@@ -84,7 +93,13 @@ export default class Twitter extends Media {
|
|
|
84
93
|
tweet += "</div>";
|
|
85
94
|
|
|
86
95
|
// Add to DOM
|
|
87
|
-
|
|
96
|
+
// The whole tweet is assembled from the oEmbed response's own HTML
|
|
97
|
+
// plus five string-concatenated fields, and that API does not escape
|
|
98
|
+
// HTML — so the result is untrusted third-party markup and goes
|
|
99
|
+
// through the sanitizer. It also repairs the four unguarded
|
|
100
|
+
// positional splits above: a markup change upstream now degrades to a
|
|
101
|
+
// missing date instead of throwing.
|
|
102
|
+
this._el.content_item?.appendChild(sanitizeSlideText(tweet));
|
|
88
103
|
|
|
89
104
|
// After Loaded
|
|
90
105
|
this.onLoaded();
|
package/src/media/types/Video.ts
CHANGED
|
@@ -1,84 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import Dom from "../../dom/Dom";
|
|
3
|
-
import { Language } from "../../language/Language";
|
|
1
|
+
import { HtmlMediaBase, type HtmlMediaKind } from "./HtmlMedia";
|
|
4
2
|
|
|
5
|
-
/* Media.
|
|
3
|
+
/* Media.Video
|
|
4
|
+
A <video> element with a single <source> child.
|
|
6
5
|
================================================== */
|
|
7
6
|
|
|
8
|
-
export default class Video extends
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
"video",
|
|
20
|
-
"vco-media-item vco-media-video vco-media-shadow",
|
|
21
|
-
this._el.content,
|
|
22
|
-
);
|
|
23
|
-
const media_item = this._el.content_item as HTMLMediaElement;
|
|
24
|
-
media_item.controls = true;
|
|
25
|
-
this._el.source_item = Dom.create("source", "", this._el.content_item);
|
|
26
|
-
const source_item = this._el.source_item as HTMLSourceElement;
|
|
27
|
-
|
|
28
|
-
// Media Loaded Event
|
|
29
|
-
media_item.addEventListener("canplay", () => {
|
|
30
|
-
this.onLoaded();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// Load Error Event (the source element fires it, not the media element)
|
|
34
|
-
source_item.addEventListener("error", () => {
|
|
35
|
-
this.loadErrorDisplay(Language.messages.error + " " + this.options.media_name);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
source_item.src = this.data.url;
|
|
39
|
-
const media_type = this._getType(this.data.url, this.data.mediatype.match_str);
|
|
40
|
-
if (media_type) {
|
|
41
|
-
source_item.type = media_type;
|
|
42
|
-
}
|
|
43
|
-
// append as a text node: re-serializing innerHTML would replace the
|
|
44
|
-
// source element and drop its error listener, leaving the loading
|
|
45
|
-
// message on screen forever
|
|
46
|
-
media_item.appendChild(
|
|
47
|
-
document.createTextNode(
|
|
48
|
-
"Your browser doesn't support HTML5 video with " + source_item.type,
|
|
49
|
-
),
|
|
50
|
-
);
|
|
51
|
-
this.player_element = media_item;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Update Media Display
|
|
55
|
-
_updateMediaDisplay() {
|
|
56
|
-
// video height is CSS-driven; nothing to compute here
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
_stopMedia() {
|
|
60
|
-
if (this.player_element) {
|
|
61
|
-
this.player_element.pause();
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
_getType(url: string, reg: string | RegExp) {
|
|
66
|
-
const ext = url.match(reg);
|
|
67
|
-
let type = "video/";
|
|
68
|
-
if (!ext) {
|
|
69
|
-
return type;
|
|
70
|
-
}
|
|
71
|
-
switch (ext[1]) {
|
|
72
|
-
case "mp4":
|
|
73
|
-
type += "mp4";
|
|
74
|
-
break;
|
|
75
|
-
case "webm":
|
|
76
|
-
type += "webm";
|
|
77
|
-
break;
|
|
78
|
-
default:
|
|
79
|
-
type = "";
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
return type;
|
|
7
|
+
export default class Video extends HtmlMediaBase {
|
|
8
|
+
protected spec() {
|
|
9
|
+
return {
|
|
10
|
+
kind: "video" as HtmlMediaKind,
|
|
11
|
+
extensions: { mp4: "mp4", webm: "webm" },
|
|
12
|
+
};
|
|
83
13
|
}
|
|
84
14
|
}
|
package/src/media/types/Vimeo.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
import { vimeoId } 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.Vimeo
|
|
7
6
|
================================================== */
|
|
@@ -14,7 +13,7 @@ export default class Vimeo extends Media {
|
|
|
14
13
|
================================================== */
|
|
15
14
|
_loadMedia() {
|
|
16
15
|
// Loading Message
|
|
17
|
-
this.
|
|
16
|
+
this.loadingMessage();
|
|
18
17
|
|
|
19
18
|
// Create Dom element
|
|
20
19
|
this._el.content_item = Dom.create(
|
|
@@ -24,17 +23,19 @@ export default class Vimeo extends Media {
|
|
|
24
23
|
);
|
|
25
24
|
|
|
26
25
|
// Get Media ID
|
|
27
|
-
|
|
28
|
-
if (!
|
|
26
|
+
this.media_id = vimeoId(this._url()) ?? "";
|
|
27
|
+
if (!this.media_id) {
|
|
29
28
|
throw new Error("Invalid Vimeo URL");
|
|
30
29
|
}
|
|
31
|
-
this.media_id = parts[1].split(/[?&]/)[0];
|
|
32
30
|
|
|
33
|
-
// API URL
|
|
31
|
+
// API URL — plain `&` separators. The HTML entity `&` 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.
|
|
34
35
|
const api_url =
|
|
35
36
|
"https://player.vimeo.com/video/" +
|
|
36
37
|
this.media_id +
|
|
37
|
-
"?api=1&title=0&
|
|
38
|
+
"?api=1&title=0&byline=0&portrait=0&color=ffffff";
|
|
38
39
|
|
|
39
40
|
this.player = Dom.create("iframe", "", this._el.content_item) as HTMLIFrameElement;
|
|
40
41
|
this.player.width = "100%";
|
|
@@ -48,8 +49,7 @@ export default class Vimeo extends Media {
|
|
|
48
49
|
|
|
49
50
|
// Update Media Display
|
|
50
51
|
_updateMediaDisplay() {
|
|
51
|
-
this.
|
|
52
|
-
ratio.r16_9({ w: this._el.content_item.offsetWidth }) + "px";
|
|
52
|
+
this._sizeContentItemTo16x9();
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
_stopMedia() {
|
|
@@ -59,7 +59,7 @@ export default class Vimeo extends Media {
|
|
|
59
59
|
"https://player.vimeo.com",
|
|
60
60
|
);
|
|
61
61
|
} catch (err) {
|
|
62
|
-
console.
|
|
62
|
+
console.warn("StoryMapJS: error pausing Vimeo player.", err);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|