@projektemacher/storymapjs 0.10.7 → 0.10.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG +350 -19
- package/README.md +43 -9
- package/dist/assets/demo-DBpeF31K.js +1 -0
- package/dist/assets/harness-Cr0rYpvt.js +1 -0
- package/dist/assets/harness-multi-CYHgI0a9.js +1 -0
- package/dist/assets/harness-support-Do7sIp2j.js +1 -0
- package/dist/assets/index-wHPqGrBS.js +1 -0
- package/dist/assets/main-DXalctuR.js +17 -0
- package/dist/context.json +12 -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 +2 -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 +1604 -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/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/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 +197 -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/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/StorymapData.html +71 -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 +105 -0
- package/dist/docs/api/interfaces/StorymapManifestBackground.html +81 -0
- package/dist/docs/api/interfaces/StorymapManifestCanvas.html +140 -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 +532 -0
- package/dist/docs/api/interfaces/StorymapOverlayLayer.html +126 -0
- package/dist/docs/api/interfaces/StorymapSlide.html +132 -0
- package/dist/docs/api/interfaces/StorymapSlideBackground.html +72 -0
- package/dist/docs/api/interfaces/StorymapSlideLocation.html +117 -0
- package/dist/docs/api/interfaces/StorymapSlideMarker.html +104 -0
- package/dist/docs/api/interfaces/StorymapSlideMedia.html +110 -0
- package/dist/docs/api/interfaces/StorymapSlideNarration.html +65 -0
- package/dist/docs/api/interfaces/StorymapSlideText.html +72 -0
- package/dist/docs/api/interfaces/StorymapTilejson.html +105 -0
- package/dist/docs/api/media/es.json +31 -0
- package/dist/docs/api/media/migration-from-knightlab.md +359 -0
- package/dist/docs/api/modules.html +50 -0
- package/dist/docs/api/types/ContentState.html +70 -0
- package/dist/docs/api/types/ImagereadyKind.html +34 -0
- package/dist/docs/api/types/MediaTypeMatch.html +78 -0
- package/dist/docs/api/types/TileSourceFactory.html +53 -0
- package/dist/docs/authoring.html +293 -0
- package/dist/docs/iiif.html +617 -62
- package/dist/docs/migration.html +313 -11
- package/dist/docs/readme.html +40 -9
- package/dist/embed/index.html +1 -1
- 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/map-area-overlays.json +68 -0
- package/dist/examples/no-map.json +44 -0
- package/dist/examples-iiif/annotated-image.json +188 -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/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/map-area-overlays.json +289 -0
- package/dist/examples-iiif/marktwain.json +255 -58
- 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/harness-multi.html +17 -0
- package/dist/harness.html +3 -2
- package/dist/index.html +16 -10
- package/dist/js/storymap.d.ts +1439 -114
- package/dist/js/storymap.js +24654 -21936
- package/dist/js/storymap.js.map +1 -1
- package/dist/navplace-properties.json +40 -0
- package/docs/migration-from-knightlab.md +229 -9
- package/docs/storymap-as-iiif-manifest.md +559 -135
- package/package.json +11 -8
- package/schema/storymap.schema.json +431 -78
- 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 +255 -193
- package/src/core/mixins.ts +24 -7
- 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 +199 -25
- package/src/language/locale/.expected-gaps.json +86 -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 +12 -1
- package/src/language/locale/el.json +15 -2
- package/src/language/locale/en.json +6 -2
- 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 +92 -0
- package/src/map/Map.ts +183 -106
- package/src/map/MapMarker.ts +28 -5
- package/src/map/georeference.ts +325 -0
- package/src/map/openlayers/Map.OpenLayers.ts +850 -237
- package/src/map/openlayers/MapMarker.OpenLayers.ts +248 -24
- package/src/map/openlayers/zoomifyTiles.ts +1 -4
- package/src/media/EmbedUtil.ts +308 -24
- package/src/media/Media.ts +243 -55
- package/src/media/embedId.ts +104 -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 +9 -9
- package/src/media/types/GoogleDoc.ts +3 -4
- package/src/media/types/HtmlMedia.ts +167 -0
- package/src/media/types/IFrame.ts +3 -4
- package/src/media/types/Image.ts +72 -6
- package/src/media/types/Juxtapose.ts +14 -5
- package/src/media/types/SoundCloud.ts +28 -6
- package/src/media/types/Text.ts +19 -13
- package/src/media/types/Twitter.ts +27 -14
- package/src/media/types/Video.ts +9 -79
- package/src/media/types/Vimeo.ts +10 -10
- package/src/media/types/Website.ts +23 -13
- package/src/media/types/Wikipedia.ts +18 -8
- package/src/media/types/YouTube.ts +71 -39
- package/src/scss/Typography.scss +1 -3
- package/src/scss/VCO.StoryMap.Dark.scss +18 -6
- package/src/scss/VCO.StoryMap.scss +37 -6
- package/src/scss/Variables.Dark.scss +3 -2
- package/src/scss/Variables.scss +3 -2
- package/src/scss/core/Mixins.scss +5 -63
- 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.MapMarker.scss +98 -3
- package/src/scss/media/VCO.Media.scss +7 -10
- package/src/scss/media/types/VCO.Media.Text.scss +8 -0
- package/src/scss/media/types/VCO.Media.Wikipedia.scss +2 -1
- package/src/scss/slider/VCO.Slide.scss +13 -3
- package/src/scss/slider/VCO.SlideNav.scss +11 -17
- package/src/scss/slider/VCO.StorySlider.scss +4 -2
- package/src/scss/ui/VCO.Consent.scss +44 -0
- package/src/scss/ui/VCO.MenuBar.Button.scss +8 -0
- package/src/scss/ui/VCO.Message.scss +2 -5
- package/src/site/site.ts +2 -1
- package/src/slider/Slide.ts +121 -27
- package/src/slider/SlideNav.ts +39 -5
- package/src/slider/StorySlider.ts +153 -42
- package/src/storymap/Consent.ts +407 -82
- package/src/storymap/StoryMap.ts +1192 -182
- package/src/storymap/content-state.ts +185 -0
- package/src/storymap/iiif.ts +1526 -68
- package/src/storymap/to-iiif.ts +921 -0
- package/src/storymap/validate.ts +80 -7
- package/src/types.ts +223 -26
- package/src/ui/MenuBar.ts +98 -45
- package/src/ui/Message.ts +9 -0
- package/src/ui/Swipable.ts +145 -78
- 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/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/Media.ts
CHANGED
|
@@ -1,16 +1,55 @@
|
|
|
1
|
-
import { mergeData } from "../core/Util";
|
|
1
|
+
import { mergeData, ratio, clearTimer } from "../core/Util";
|
|
2
2
|
import { Evented, type EventedInstance } from "../core/mixins";
|
|
3
3
|
import Dom from "../dom/Dom";
|
|
4
4
|
import Message from "../ui/Message";
|
|
5
5
|
import { Browser } from "../core/Browser";
|
|
6
6
|
import { MediaState, StorymapSlideMedia } from "../types";
|
|
7
|
-
import {
|
|
7
|
+
import { Language } from "../language/Language";
|
|
8
|
+
import { consentManagerOf, consentMessage, mediaService } from "../storymap/Consent";
|
|
9
|
+
import { validateWebURL, sanitizeSlideText } from "./EmbedUtil";
|
|
8
10
|
import { loadJS } from "../core/Load";
|
|
9
11
|
/* VCO.Media
|
|
10
12
|
Main media template for media assets.
|
|
11
13
|
Takes a data object and populates a dom object
|
|
12
14
|
================================================== */
|
|
13
15
|
|
|
16
|
+
/**
|
|
17
|
+
* The icon glyph each media type shows in its error state.
|
|
18
|
+
*
|
|
19
|
+
* The icon font does not carry a glyph for every registered type, and the
|
|
20
|
+
* class used to be built straight from `media_type`, so dailymotion, audio,
|
|
21
|
+
* googledocs, iframe, documentcloud, juxtapose and website rendered an empty
|
|
22
|
+
* box next to the error text. The mapping is explicit rather than derived, so
|
|
23
|
+
* a type added later falls back to a real glyph instead of a blank one —
|
|
24
|
+
* `tests/embed-util-media.test.ts` checks the whole table against the font.
|
|
25
|
+
*/
|
|
26
|
+
const LOAD_ERROR_ICONS: Record<string, string> = {
|
|
27
|
+
youtube: "youtube",
|
|
28
|
+
vimeo: "vimeo",
|
|
29
|
+
dailymotion: "video",
|
|
30
|
+
soundcloud: "soundcloud",
|
|
31
|
+
twitter: "twitter",
|
|
32
|
+
flickr: "flickr",
|
|
33
|
+
image: "image",
|
|
34
|
+
video: "video",
|
|
35
|
+
audio: "music",
|
|
36
|
+
googledocs: "doc",
|
|
37
|
+
wikipedia: "wikipedia",
|
|
38
|
+
iframe: "web",
|
|
39
|
+
facebook: "facebook",
|
|
40
|
+
documentcloud: "doc",
|
|
41
|
+
juxtapose: "image",
|
|
42
|
+
blockquote: "blockquote",
|
|
43
|
+
website: "web",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const GENERIC_LOAD_ERROR_ICON = "web";
|
|
47
|
+
|
|
48
|
+
export function loadErrorIcon(media_type: unknown): string {
|
|
49
|
+
const type = typeof media_type === "string" ? media_type : "";
|
|
50
|
+
return LOAD_ERROR_ICONS[type] ?? GENERIC_LOAD_ERROR_ICON;
|
|
51
|
+
}
|
|
52
|
+
|
|
14
53
|
/* Options for Media and its subclasses: the fields Media itself sets
|
|
15
54
|
or reads. Everything else merged in via mergeData is absorbed by the
|
|
16
55
|
index signature. */
|
|
@@ -29,30 +68,50 @@ export interface MediaOptions {
|
|
|
29
68
|
/* Data for media assets: the shared exchange format plus the link
|
|
30
69
|
fields the base layout renders. */
|
|
31
70
|
export interface MediaData extends StorymapSlideMedia {
|
|
32
|
-
uniqueid?: string;
|
|
33
|
-
link?: string;
|
|
34
|
-
link_target?: string;
|
|
71
|
+
uniqueid?: string | null;
|
|
72
|
+
link?: string | null;
|
|
73
|
+
link_target?: string | null;
|
|
35
74
|
[key: string]: unknown;
|
|
36
75
|
}
|
|
37
76
|
|
|
77
|
+
/**
|
|
78
|
+
* The media element cache.
|
|
79
|
+
*
|
|
80
|
+
* `content_item`, `content_link`, `caption` and `credit` are only created
|
|
81
|
+
* once `_loadMedia()` / `showMeta()` have run, so they start out null rather
|
|
82
|
+
* than as an empty element — that is what the "did the load happen?" check is
|
|
83
|
+
* for, and pretending otherwise with `{} as HTMLElement` is what let the
|
|
84
|
+
* consent-denied path dereference `undefined.style`.
|
|
85
|
+
*/
|
|
86
|
+
type MediaElements = {
|
|
87
|
+
container: HTMLElement;
|
|
88
|
+
content_container: HTMLElement;
|
|
89
|
+
content: HTMLElement;
|
|
90
|
+
content_item: HTMLElement | null;
|
|
91
|
+
content_link: HTMLElement | null;
|
|
92
|
+
source_item: HTMLSourceElement | null;
|
|
93
|
+
caption: HTMLElement | null;
|
|
94
|
+
credit: HTMLElement | null;
|
|
95
|
+
parent: HTMLElement;
|
|
96
|
+
link: HTMLElement | null;
|
|
97
|
+
};
|
|
98
|
+
|
|
38
99
|
export class MediaBase {
|
|
39
|
-
declare "_el":
|
|
100
|
+
declare "_el": MediaElements;
|
|
40
101
|
declare "player": unknown;
|
|
41
|
-
declare "timer": ReturnType<typeof setTimeout
|
|
42
|
-
declare "load_timer": ReturnType<typeof setTimeout
|
|
102
|
+
declare "timer": ReturnType<typeof setTimeout> | null;
|
|
103
|
+
declare "load_timer": ReturnType<typeof setTimeout> | null;
|
|
43
104
|
declare "load_controller": AbortController | null;
|
|
44
|
-
declare "message": Message;
|
|
105
|
+
declare "message": Message | null;
|
|
45
106
|
declare "media_id": unknown;
|
|
46
107
|
declare "_state": MediaState;
|
|
108
|
+
declare "_disposed": boolean;
|
|
47
109
|
declare "data": MediaData;
|
|
48
110
|
declare "options": MediaOptions;
|
|
49
111
|
declare "animator": unknown;
|
|
50
112
|
declare "_media": unknown;
|
|
51
|
-
declare "_": (key: string) => string;
|
|
52
113
|
declare "fire": EventedInstance["fire"];
|
|
53
114
|
|
|
54
|
-
//_el: {},
|
|
55
|
-
|
|
56
115
|
/* Constructor
|
|
57
116
|
================================================== */
|
|
58
117
|
constructor(data: MediaData, options?: MediaOptions, add_to_container?: HTMLElement) {
|
|
@@ -61,8 +120,9 @@ export class MediaBase {
|
|
|
61
120
|
container: {} as HTMLElement,
|
|
62
121
|
content_container: {} as HTMLElement,
|
|
63
122
|
content: {} as HTMLElement,
|
|
64
|
-
content_item:
|
|
65
|
-
content_link:
|
|
123
|
+
content_item: null,
|
|
124
|
+
content_link: null,
|
|
125
|
+
source_item: null,
|
|
66
126
|
caption: null,
|
|
67
127
|
credit: null,
|
|
68
128
|
parent: {} as HTMLElement,
|
|
@@ -89,6 +149,7 @@ export class MediaBase {
|
|
|
89
149
|
show_meta: false,
|
|
90
150
|
media_loaded: false,
|
|
91
151
|
};
|
|
152
|
+
this._disposed = false;
|
|
92
153
|
|
|
93
154
|
// Data
|
|
94
155
|
this.data = {
|
|
@@ -132,8 +193,14 @@ export class MediaBase {
|
|
|
132
193
|
const manager = consentManagerOf(this.options);
|
|
133
194
|
if (this.options.consent_required && manager && this.options.media_type) {
|
|
134
195
|
// GDPR consent mode: ask before loading anything from this
|
|
135
|
-
// external service
|
|
136
|
-
|
|
196
|
+
// external service. media_type is the stable identity (the
|
|
197
|
+
// MediaType slug) and media_name is the display name — using
|
|
198
|
+
// the slug as the label made this panel ask "Load content from
|
|
199
|
+
// youtube?" where the start-of-story dialog said "YouTube".
|
|
200
|
+
const service = mediaService(
|
|
201
|
+
this.options.media_type,
|
|
202
|
+
(this.options.media_name as string | undefined) ?? "",
|
|
203
|
+
);
|
|
137
204
|
let host = "";
|
|
138
205
|
try {
|
|
139
206
|
host = new URL((this.data as { url?: string })?.url ?? "").host;
|
|
@@ -175,49 +242,65 @@ export class MediaBase {
|
|
|
175
242
|
const target = (this._el.content_container ?? this._el.container) as HTMLElement;
|
|
176
243
|
const blocked = document.createElement("div");
|
|
177
244
|
blocked.className = "vco-consent-blocked";
|
|
245
|
+
// the display name, not the slug — see loadMedia()
|
|
246
|
+
const service_name =
|
|
247
|
+
(this.options.media_name as string | undefined) ||
|
|
248
|
+
(this.options.media_type as string | undefined) ||
|
|
249
|
+
"";
|
|
178
250
|
blocked.textContent = (
|
|
179
251
|
consentMessage("consent_blocked", "Content from {service} is blocked.") as string
|
|
180
|
-
).replace("{service}",
|
|
252
|
+
).replace("{service}", service_name);
|
|
181
253
|
target.append(blocked);
|
|
182
254
|
this.onLoaded(true);
|
|
183
255
|
}
|
|
184
256
|
|
|
185
|
-
|
|
186
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Look up a UI string for the active language, falling back to the
|
|
259
|
+
* English default (which `setLanguage` already merges in) and finally to
|
|
260
|
+
* the key itself, so a missing translation degrades to something visible
|
|
261
|
+
* rather than "undefined".
|
|
262
|
+
*/
|
|
263
|
+
_(key: string): string {
|
|
264
|
+
return Language.messages[key] ?? key;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Show the loading overlay for this media item. */
|
|
268
|
+
loadingMessage(): void {
|
|
269
|
+
this.message?.updateMessage(this._("loading") + " " + this.options.media_name);
|
|
187
270
|
}
|
|
188
271
|
|
|
189
272
|
updateMediaDisplay(layout?: string) {
|
|
190
|
-
|
|
191
|
-
|
|
273
|
+
// `content_item` only exists once a media type's `_loadMedia()` has
|
|
274
|
+
// run. It stays null when a consent decision blocked the load, so the
|
|
275
|
+
// sizing below has to be skipped rather than dereference a
|
|
276
|
+
// placeholder — that was the crash on the denied path.
|
|
277
|
+
const content_item = this._el.content_item;
|
|
278
|
+
if (!this._state.loaded || !content_item) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
192
281
|
|
|
193
|
-
|
|
194
|
-
this._el.content_item.style.maxHeight = this.options.height / 2 + "px";
|
|
195
|
-
}
|
|
282
|
+
this._updateMediaDisplay(layout);
|
|
196
283
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
if (this._el.caption) {
|
|
202
|
-
this._el.caption.style.width = "auto";
|
|
203
|
-
}
|
|
204
|
-
}
|
|
284
|
+
if (!Browser.mobile && layout !== "portrait") {
|
|
285
|
+
content_item.style.maxHeight = Number(this.options.height ?? 0) / 2 + "px";
|
|
286
|
+
}
|
|
205
287
|
|
|
206
|
-
|
|
207
|
-
|
|
288
|
+
if (layout === "portrait") {
|
|
289
|
+
content_item.style.maxHeight = "none";
|
|
290
|
+
}
|
|
291
|
+
if (this._state.media_loaded) {
|
|
292
|
+
const width = content_item.offsetWidth + "px";
|
|
293
|
+
if (this._el.credit) {
|
|
294
|
+
this._el.credit.style.width = width;
|
|
208
295
|
}
|
|
209
|
-
if (this.
|
|
210
|
-
|
|
211
|
-
this._el.credit.style.width = this._el.content_item.offsetWidth + "px";
|
|
212
|
-
}
|
|
213
|
-
if (this._el.caption) {
|
|
214
|
-
this._el.caption.style.width = this._el.content_item.offsetWidth + "px";
|
|
215
|
-
}
|
|
296
|
+
if (this._el.caption) {
|
|
297
|
+
this._el.caption.style.width = width;
|
|
216
298
|
}
|
|
217
299
|
}
|
|
218
300
|
}
|
|
219
301
|
|
|
220
|
-
|
|
302
|
+
/**
|
|
303
|
+
* Media Specific
|
|
221
304
|
================================================== */
|
|
222
305
|
_loadMedia() {}
|
|
223
306
|
|
|
@@ -225,6 +308,24 @@ export class MediaBase {
|
|
|
225
308
|
//this._el.content_item.style.maxHeight = (this.options.height - this.options.credit_height - this.options.caption_height - 16) + "px";
|
|
226
309
|
}
|
|
227
310
|
|
|
311
|
+
/** Size the media box to the `height` option, in pixels. */
|
|
312
|
+
_sizeContentItemToOptionHeight(): void {
|
|
313
|
+
if (this._el.content_item) {
|
|
314
|
+
this._el.content_item.style.height = Number(this.options.height ?? 0) + "px";
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Size the media box to a 16:9 box matching its current width — the
|
|
320
|
+
* aspect ratio every video provider embeds at.
|
|
321
|
+
*/
|
|
322
|
+
_sizeContentItemTo16x9(): void {
|
|
323
|
+
const item = this._el.content_item;
|
|
324
|
+
if (item) {
|
|
325
|
+
item.style.height = ratio.r16_9({ w: item.offsetWidth }) + "px";
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
228
329
|
/* Public
|
|
229
330
|
================================================== */
|
|
230
331
|
show() {}
|
|
@@ -241,6 +342,45 @@ export class MediaBase {
|
|
|
241
342
|
this.onRemove();
|
|
242
343
|
}
|
|
243
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Terminal teardown: cancel pending work, stop playback, release the
|
|
347
|
+
* media-specific player and drop the DOM. Called by `Slide.dispose()`;
|
|
348
|
+
* the media must not be used afterwards.
|
|
349
|
+
*/
|
|
350
|
+
dispose() {
|
|
351
|
+
if (this._disposed) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
this._disposed = true;
|
|
355
|
+
|
|
356
|
+
// a load queued by loadMedia() that never started
|
|
357
|
+
if (this.load_timer) {
|
|
358
|
+
clearTimer(this.load_timer);
|
|
359
|
+
this.load_timer = null;
|
|
360
|
+
}
|
|
361
|
+
if (this.timer) {
|
|
362
|
+
clearTimer(this.timer);
|
|
363
|
+
this.timer = null;
|
|
364
|
+
}
|
|
365
|
+
// an external script still in flight (YouTube, Vimeo, Twitter, ...)
|
|
366
|
+
this.load_controller?.abort();
|
|
367
|
+
this.load_controller = null;
|
|
368
|
+
|
|
369
|
+
// let the concrete type tear down its player before the DOM goes away
|
|
370
|
+
this._disposeMedia();
|
|
371
|
+
|
|
372
|
+
this._el.container?.getAnimations?.().forEach((a) => a.cancel());
|
|
373
|
+
this.message?.dispose?.();
|
|
374
|
+
this.message = null;
|
|
375
|
+
this._el.container?.remove();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Media-specific teardown. Overridden by types that own a player, an
|
|
380
|
+
* embedded document or a listening widget.
|
|
381
|
+
*/
|
|
382
|
+
_disposeMedia() {}
|
|
383
|
+
|
|
244
384
|
// Update Display
|
|
245
385
|
updateDisplay(w?: number, h?: number, l?: string) {
|
|
246
386
|
this._updateDisplay(w, h, l);
|
|
@@ -251,7 +391,8 @@ export class MediaBase {
|
|
|
251
391
|
// load delay): avoids building iframes and injecting scripts for a
|
|
252
392
|
// slide the visitor already skipped past
|
|
253
393
|
if (!this._state.loaded && this.load_timer) {
|
|
254
|
-
|
|
394
|
+
clearTimer(this.load_timer);
|
|
395
|
+
this.load_timer = null;
|
|
255
396
|
this.load_timer = null;
|
|
256
397
|
}
|
|
257
398
|
// Abort an in-flight external script load, if any
|
|
@@ -288,8 +429,18 @@ export class MediaBase {
|
|
|
288
429
|
"vco-media-item vco-media-loaderror",
|
|
289
430
|
this._el.content,
|
|
290
431
|
);
|
|
291
|
-
|
|
292
|
-
|
|
432
|
+
// The icon font has no glyph for every media type (dailymotion, audio,
|
|
433
|
+
// googledocs, iframe, documentcloud, juxtapose and website had none),
|
|
434
|
+
// and the class was built by string concatenation, so those error
|
|
435
|
+
// states rendered an empty box. Map the missing ones to a glyph that
|
|
436
|
+
// exists, and fall back to a generic "web" icon for anything added
|
|
437
|
+
// later.
|
|
438
|
+
this._el.content_item.appendChild(
|
|
439
|
+
Dom.create("div", `vco-icon-${loadErrorIcon(this.options.media_type)}`),
|
|
440
|
+
);
|
|
441
|
+
const text = Dom.create("p", "");
|
|
442
|
+
text.appendChild(document.createTextNode(message));
|
|
443
|
+
this._el.content_item.appendChild(text);
|
|
293
444
|
|
|
294
445
|
// After Loaded
|
|
295
446
|
this.onLoaded(true);
|
|
@@ -312,27 +463,35 @@ export class MediaBase {
|
|
|
312
463
|
onMediaLoaded(e?: unknown) {
|
|
313
464
|
this._state.media_loaded = true;
|
|
314
465
|
this.fire("media_loaded", this.data);
|
|
466
|
+
const width = (this._el.content_item?.offsetWidth ?? 0) + "px";
|
|
315
467
|
if (this._el.credit) {
|
|
316
|
-
this._el.credit.style.width =
|
|
468
|
+
this._el.credit.style.width = width;
|
|
317
469
|
}
|
|
318
470
|
if (this._el.caption) {
|
|
319
|
-
this._el.caption.style.width =
|
|
471
|
+
this._el.caption.style.width = width;
|
|
320
472
|
}
|
|
321
473
|
}
|
|
322
474
|
|
|
323
|
-
|
|
475
|
+
/** Render the media credit and caption, if the slide has them. */
|
|
476
|
+
showMeta(): void {
|
|
324
477
|
this._state.show_meta = true;
|
|
325
|
-
// Credit
|
|
326
|
-
|
|
478
|
+
// Credit and caption are author-supplied strings that may legitimately
|
|
479
|
+
// contain formatting (they are documented as HTML), so they go through
|
|
480
|
+
// the same sanitizer as the slide text rather than straight to
|
|
481
|
+
// innerHTML — the JSON is untrusted input, and these were the two
|
|
482
|
+
// easiest stored-XSS sinks in the viewer.
|
|
483
|
+
const credit = this._credit();
|
|
484
|
+
if (credit && credit !== "" && !this._el.credit) {
|
|
327
485
|
this._el.credit = Dom.create("div", "vco-credit", this._el.content_container);
|
|
328
|
-
this._el.credit.
|
|
486
|
+
this._el.credit.appendChild(sanitizeSlideText(credit));
|
|
329
487
|
this.options.credit_height = this._el.credit.offsetHeight;
|
|
330
488
|
}
|
|
331
489
|
|
|
332
490
|
// Caption
|
|
333
|
-
|
|
491
|
+
const caption = this._caption();
|
|
492
|
+
if (caption && caption !== "" && !this._el.caption) {
|
|
334
493
|
this._el.caption = Dom.create("div", "vco-caption", this._el.content_container);
|
|
335
|
-
this._el.caption.
|
|
494
|
+
this._el.caption.appendChild(sanitizeSlideText(caption));
|
|
336
495
|
this.options.caption_height = this._el.caption.offsetHeight;
|
|
337
496
|
}
|
|
338
497
|
}
|
|
@@ -347,6 +506,21 @@ export class MediaBase {
|
|
|
347
506
|
|
|
348
507
|
/* Private Methods
|
|
349
508
|
================================================== */
|
|
509
|
+
/** The media URL, normalised to a string. */
|
|
510
|
+
_url(): string {
|
|
511
|
+
return typeof this.data.url === "string" ? this.data.url : "";
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** The media caption, or null when the slide has none. */
|
|
515
|
+
_caption(): string | null {
|
|
516
|
+
return typeof this.data.caption === "string" ? this.data.caption : null;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/** The media credit, or null when the slide has none. */
|
|
520
|
+
_credit(): string | null {
|
|
521
|
+
return typeof this.data.credit === "string" ? this.data.credit : null;
|
|
522
|
+
}
|
|
523
|
+
|
|
350
524
|
_initLayout() {
|
|
351
525
|
// Message
|
|
352
526
|
this.message = new Message({}, this.options);
|
|
@@ -360,15 +534,29 @@ export class MediaBase {
|
|
|
360
534
|
);
|
|
361
535
|
|
|
362
536
|
// Link
|
|
363
|
-
|
|
537
|
+
// The link target comes from the storymap JSON, so it has to pass the
|
|
538
|
+
// same protocol check as every other author-supplied URL — otherwise a
|
|
539
|
+
// `javascript:` href is a click-through XSS. A rejected link falls
|
|
540
|
+
// through to the unlinked layout below rather than rendering a
|
|
541
|
+
// dead anchor.
|
|
542
|
+
// (`_el.content` starts as a truthy `{}` placeholder, so the branch is
|
|
543
|
+
// tracked with a local flag rather than a truthiness test.)
|
|
544
|
+
const raw_link = this.data.link;
|
|
545
|
+
const href = typeof raw_link === "string" ? validateWebURL(raw_link) : null;
|
|
546
|
+
if (href) {
|
|
364
547
|
this._el.link = Dom.create("a", "vco-media-link", this._el.content_container);
|
|
365
548
|
const link = this._el.link as HTMLAnchorElement;
|
|
366
|
-
link.href =
|
|
549
|
+
link.href = href;
|
|
367
550
|
if (this.data.link_target && this.data.link_target !== "") {
|
|
368
551
|
link.target = this.data.link_target;
|
|
369
552
|
} else {
|
|
370
553
|
link.target = "_blank";
|
|
371
554
|
}
|
|
555
|
+
if (link.target === "_blank") {
|
|
556
|
+
// rel=noopener so the opened page cannot reach back through
|
|
557
|
+
// window.opener
|
|
558
|
+
link.rel = "noopener noreferrer";
|
|
559
|
+
}
|
|
372
560
|
|
|
373
561
|
this._el.content = Dom.create("div", "vco-media-content", this._el.link);
|
|
374
562
|
} else {
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* embedId
|
|
2
|
+
Provider id extraction.
|
|
3
|
+
|
|
4
|
+
Each media type used to roll its own: six different ways of stripping the
|
|
5
|
+
query string, three different failure modes (throw an Error, throw a bare
|
|
6
|
+
string, or log a warning and carry on with `undefined`), and a fourth
|
|
7
|
+
divergence between the URL shapes the code accepted and the ones
|
|
8
|
+
`MediaType`'s routing regex actually matched.
|
|
9
|
+
|
|
10
|
+
These helpers are the single implementation. Each returns null when the
|
|
11
|
+
url does not carry that provider's id, and the caller decides how to
|
|
12
|
+
report it.
|
|
13
|
+
================================================== */
|
|
14
|
+
|
|
15
|
+
/** Strip the query string and fragment. */
|
|
16
|
+
function withoutQuery(url: string): string {
|
|
17
|
+
return url.split(/[?#]/)[0];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The first path segment after any of `markers`, with the query string
|
|
22
|
+
* removed. Returns null when none of the markers is present.
|
|
23
|
+
*/
|
|
24
|
+
export function segmentAfter(url: string, ...markers: RegExp[]): string | null {
|
|
25
|
+
for (const marker of markers) {
|
|
26
|
+
const match = url.match(marker);
|
|
27
|
+
if (match) {
|
|
28
|
+
const rest = url.slice((match.index ?? 0) + match[0].length);
|
|
29
|
+
const segment = withoutQuery(rest).split("/")[0];
|
|
30
|
+
if (segment) {
|
|
31
|
+
return segment;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A query parameter, via the platform parser rather than a hand-rolled split. */
|
|
39
|
+
export function queryParam(url: string, name: string): string | null {
|
|
40
|
+
try {
|
|
41
|
+
return new URL(url).searchParams.get(name);
|
|
42
|
+
} catch {
|
|
43
|
+
// not an absolute URL; fall back to the raw query string
|
|
44
|
+
const query = url.split("?")[1];
|
|
45
|
+
if (!query) return null;
|
|
46
|
+
for (const pair of query.split("&")) {
|
|
47
|
+
const [key, value] = pair.split("=");
|
|
48
|
+
if (key === name) {
|
|
49
|
+
return value ?? "";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** YouTube video id: watch, embed, short, shorts, live and youtu.be links. */
|
|
57
|
+
export function youtubeId(url: string): string | null {
|
|
58
|
+
const fromQuery = queryParam(url, "v");
|
|
59
|
+
if (fromQuery) {
|
|
60
|
+
return fromQuery;
|
|
61
|
+
}
|
|
62
|
+
return segmentAfter(
|
|
63
|
+
url,
|
|
64
|
+
/youtu\.be\//i,
|
|
65
|
+
/\/embed\//i,
|
|
66
|
+
/\/shorts\//i,
|
|
67
|
+
/\/live\//i,
|
|
68
|
+
/\/v\//i,
|
|
69
|
+
/[?&]v=/i,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Vimeo video id. Watch URLs are the bare `vimeo.com/<id>` form, so the
|
|
75
|
+
* explicit `/video/` path alone is not enough — the previous implementation
|
|
76
|
+
* split on `video\/|\/\/vimeo\.com\//` and relied on the second alternative.
|
|
77
|
+
* Non-numeric pages (channels, albums, showcases) are rejected.
|
|
78
|
+
*/
|
|
79
|
+
export function vimeoId(url: string): string | null {
|
|
80
|
+
const explicit = segmentAfter(url, /vimeo\.com\/video\//i, /player\.vimeo\.com\/video\//i);
|
|
81
|
+
if (explicit) {
|
|
82
|
+
return explicit;
|
|
83
|
+
}
|
|
84
|
+
return url.match(/vimeo\.com\/(\d+)(?:$|[/?#])/i)?.[1] ?? null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Dailymotion video id from a watch or embed link. */
|
|
88
|
+
export function dailymotionId(url: string): string | null {
|
|
89
|
+
return segmentAfter(url, /dailymotion\.com\/video\//i, /dai\.ly\//i, /\/embed\/video\//i);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Flickr photo id from a photo page URL. */
|
|
93
|
+
export function flickrId(url: string): string | null {
|
|
94
|
+
const id = segmentAfter(url, /flickr\.com\/photos\/[^/]+\//i);
|
|
95
|
+
if (id && /^\d+$/.test(id)) {
|
|
96
|
+
return id;
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Tweet id from a twitter.com or x.com status URL. */
|
|
102
|
+
export function tweetId(url: string): string | null {
|
|
103
|
+
return segmentAfter(url, /\/status(?:es)?\//i);
|
|
104
|
+
}
|
package/src/media/types/Audio.ts
CHANGED
|
@@ -1,87 +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.Audio
|
|
4
|
+
An <audio> element with a single <source> child.
|
|
6
5
|
================================================== */
|
|
7
6
|
|
|
8
|
-
export default class Audio 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
|
-
"audio",
|
|
20
|
-
"vco-media-item vco-media-audio 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 audio with " + source_item.type,
|
|
49
|
-
),
|
|
50
|
-
);
|
|
51
|
-
this.player_element = media_item;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Update Media Display
|
|
55
|
-
_updateMediaDisplay() {
|
|
56
|
-
// audio 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 = "audio/";
|
|
68
|
-
if (!ext) {
|
|
69
|
-
return type;
|
|
70
|
-
}
|
|
71
|
-
switch (ext[1]) {
|
|
72
|
-
case "mp3":
|
|
73
|
-
type += "mpeg";
|
|
74
|
-
break;
|
|
75
|
-
case "wav":
|
|
76
|
-
type += "wav";
|
|
77
|
-
break;
|
|
78
|
-
case "m4a":
|
|
79
|
-
type += "mp4";
|
|
80
|
-
break;
|
|
81
|
-
default:
|
|
82
|
-
type = "";
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
return type;
|
|
7
|
+
export default class Audio extends HtmlMediaBase {
|
|
8
|
+
protected spec() {
|
|
9
|
+
return {
|
|
10
|
+
kind: "audio" as HtmlMediaKind,
|
|
11
|
+
extensions: { mp3: "mpeg", wav: "wav", m4a: "mp4" },
|
|
12
|
+
};
|
|
86
13
|
}
|
|
87
14
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Media } from "../Media";
|
|
2
2
|
import Dom from "../../dom/Dom";
|
|
3
|
-
import { Language } from "../../language/Language";
|
|
4
3
|
import { sanitizeBlockquote } from "../EmbedUtil";
|
|
5
4
|
|
|
6
5
|
/* Media.Blockquote
|
|
@@ -13,7 +12,7 @@ export default class Blockquote extends Media {
|
|
|
13
12
|
================================================== */
|
|
14
13
|
_loadMedia() {
|
|
15
14
|
// Loading Message
|
|
16
|
-
this.
|
|
15
|
+
this.loadingMessage();
|
|
17
16
|
|
|
18
17
|
// Create Dom element
|
|
19
18
|
this._el.content_item = Dom.create(
|
|
@@ -23,7 +22,7 @@ export default class Blockquote extends Media {
|
|
|
23
22
|
);
|
|
24
23
|
|
|
25
24
|
// Get Media ID
|
|
26
|
-
this.media_id = this.
|
|
25
|
+
this.media_id = this._url();
|
|
27
26
|
|
|
28
27
|
// The url field holds user-pasted blockquote markup. Sanitize it
|
|
29
28
|
// instead of injecting the raw markup, which would allow stored
|