@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/EmbedUtil.ts
CHANGED
|
@@ -21,6 +21,17 @@ const IFRAME_ATTRIBUTES = [
|
|
|
21
21
|
"title",
|
|
22
22
|
];
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* `sandbox` value for a rebuilt embed. It is deliberately *not* the most
|
|
26
|
+
* restrictive option: `allow-scripts allow-same-origin` are required by the
|
|
27
|
+
* major video providers to function, and note that the combination is only
|
|
28
|
+
* dangerous when the framed content is same-origin with the viewer, which the
|
|
29
|
+
* http(s)-only src check already rules out for the viewer itself. The value
|
|
30
|
+
* below removes the capabilities that enable clickjacking and top-level
|
|
31
|
+
* navigation.
|
|
32
|
+
*/
|
|
33
|
+
const ALLOWED_IFRAME_SANDBOX = "allow-scripts allow-same-origin allow-presentation allow-popups";
|
|
34
|
+
|
|
24
35
|
// Tags allowed to survive blockquote sanitization. Elements not listed
|
|
25
36
|
// are unwrapped (their children are kept); DROP_TAGS are removed along
|
|
26
37
|
// with their contents.
|
|
@@ -66,6 +77,150 @@ const DROP_TAGS = [
|
|
|
66
77
|
"SELECT",
|
|
67
78
|
];
|
|
68
79
|
|
|
80
|
+
// Drop list for slide text (issue #358): same as DROP_TAGS but IFRAME is
|
|
81
|
+
// rebuilt via buildIframe() instead of dropped, so extra media can be
|
|
82
|
+
// embedded in the text field.
|
|
83
|
+
const SLIDE_TEXT_DROP_TAGS = DROP_TAGS.filter((tag) => tag !== "IFRAME");
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Slide text is an allowlist, not a denylist.
|
|
87
|
+
*
|
|
88
|
+
* The previous denylist ("drop these 18 tags, keep everything else") let
|
|
89
|
+
* through `<audio>`, `<video>`, `<details>`, `<dialog>`, `<marquee>`,
|
|
90
|
+
* `<plaintext>`, `<xmp>` and friends, and copied *every* non-`on*` attribute
|
|
91
|
+
* verbatim. Two consequences worth naming:
|
|
92
|
+
*
|
|
93
|
+
* - `style` was passed through untouched, so a pasted
|
|
94
|
+
* `style="position:fixed;inset:0;z-index:2147483647;background:#fff"`
|
|
95
|
+
* painted a full-widget opaque overlay over the map and the controls:
|
|
96
|
+
* chrome spoofing plus clickjacking, from a single attribute.
|
|
97
|
+
* - `target` was only defaulted when absent, so a pasted `target="_top"`
|
|
98
|
+
* navigated the *host page* out of the viewer.
|
|
99
|
+
*
|
|
100
|
+
* This list covers prose and media embeds. Anything else is unwrapped (its
|
|
101
|
+
* text is kept) rather than dropped with its contents.
|
|
102
|
+
*/
|
|
103
|
+
const SLIDE_TEXT_TAGS = [
|
|
104
|
+
// structure / text
|
|
105
|
+
"P",
|
|
106
|
+
"BR",
|
|
107
|
+
"HR",
|
|
108
|
+
"DIV",
|
|
109
|
+
"SPAN",
|
|
110
|
+
"BLOCKQUOTE",
|
|
111
|
+
"PRE",
|
|
112
|
+
"CODE",
|
|
113
|
+
"KBD",
|
|
114
|
+
"SAMP",
|
|
115
|
+
"VAR",
|
|
116
|
+
// inline formatting
|
|
117
|
+
"EM",
|
|
118
|
+
"STRONG",
|
|
119
|
+
"B",
|
|
120
|
+
"I",
|
|
121
|
+
"U",
|
|
122
|
+
"S",
|
|
123
|
+
"STRIKE",
|
|
124
|
+
"DEL",
|
|
125
|
+
"INS",
|
|
126
|
+
"SMALL",
|
|
127
|
+
"SUB",
|
|
128
|
+
"SUP",
|
|
129
|
+
"MARK",
|
|
130
|
+
"ABBR",
|
|
131
|
+
"CITE",
|
|
132
|
+
"Q",
|
|
133
|
+
"TIME",
|
|
134
|
+
"DFN",
|
|
135
|
+
// lists
|
|
136
|
+
"UL",
|
|
137
|
+
"OL",
|
|
138
|
+
"LI",
|
|
139
|
+
"DL",
|
|
140
|
+
"DT",
|
|
141
|
+
"DD",
|
|
142
|
+
// tables
|
|
143
|
+
"TABLE",
|
|
144
|
+
"THEAD",
|
|
145
|
+
"TBODY",
|
|
146
|
+
"TFOOT",
|
|
147
|
+
"TR",
|
|
148
|
+
"TH",
|
|
149
|
+
"TD",
|
|
150
|
+
"CAPTION",
|
|
151
|
+
"COLGROUP",
|
|
152
|
+
"COL",
|
|
153
|
+
// media (the src/srcset URLs are validated)
|
|
154
|
+
"IMG",
|
|
155
|
+
"FIGURE",
|
|
156
|
+
"FIGCAPTION",
|
|
157
|
+
"PICTURE",
|
|
158
|
+
"SOURCE",
|
|
159
|
+
"AUDIO",
|
|
160
|
+
"VIDEO",
|
|
161
|
+
"TRACK",
|
|
162
|
+
// links
|
|
163
|
+
"A",
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Attributes allowed on slide-text elements. `id`/`name` are deliberately
|
|
168
|
+
* absent: they enable DOM clobbering of host-page globals. `style` is
|
|
169
|
+
* deliberately absent (see above). `class` is kept — the story fixtures and
|
|
170
|
+
* the migrated site content style slides through it, and a class name cannot
|
|
171
|
+
* execute anything.
|
|
172
|
+
*/
|
|
173
|
+
const SLIDE_TEXT_ATTRIBUTES = [
|
|
174
|
+
"class",
|
|
175
|
+
"title",
|
|
176
|
+
"lang",
|
|
177
|
+
"dir",
|
|
178
|
+
"alt",
|
|
179
|
+
"width",
|
|
180
|
+
"height",
|
|
181
|
+
"colspan",
|
|
182
|
+
"rowspan",
|
|
183
|
+
"headers",
|
|
184
|
+
"scope",
|
|
185
|
+
"datetime",
|
|
186
|
+
"cite",
|
|
187
|
+
"start",
|
|
188
|
+
"reversed",
|
|
189
|
+
"type",
|
|
190
|
+
"value",
|
|
191
|
+
"controls",
|
|
192
|
+
"loop",
|
|
193
|
+
"muted",
|
|
194
|
+
"playsinline",
|
|
195
|
+
"preload",
|
|
196
|
+
"poster",
|
|
197
|
+
"kind",
|
|
198
|
+
"srclang",
|
|
199
|
+
"label",
|
|
200
|
+
"default",
|
|
201
|
+
"sizes",
|
|
202
|
+
"loading",
|
|
203
|
+
"decoding",
|
|
204
|
+
"open",
|
|
205
|
+
// a source/track is only useful with a machine-readable kind
|
|
206
|
+
"media",
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
/** URL-bearing attributes validated to http(s) in slide text. */
|
|
210
|
+
const URL_ATTRIBUTES = [
|
|
211
|
+
"href",
|
|
212
|
+
"src",
|
|
213
|
+
"srcset",
|
|
214
|
+
"cite",
|
|
215
|
+
"data",
|
|
216
|
+
"poster",
|
|
217
|
+
"action",
|
|
218
|
+
"formaction",
|
|
219
|
+
"longdesc",
|
|
220
|
+
"profile",
|
|
221
|
+
"background",
|
|
222
|
+
];
|
|
223
|
+
|
|
69
224
|
function parseInert(html: string): Document {
|
|
70
225
|
return new DOMParser().parseFromString(html, "text/html");
|
|
71
226
|
}
|
|
@@ -110,11 +265,9 @@ export function buildIframe(html: string): HTMLIFrameElement | null {
|
|
|
110
265
|
iframe.setAttribute("src", src);
|
|
111
266
|
if (pasted) {
|
|
112
267
|
for (let i = 0; i < IFRAME_ATTRIBUTES.length; i++) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
pasted.getAttribute(IFRAME_ATTRIBUTES[i]),
|
|
117
|
-
);
|
|
268
|
+
const value = pasted.getAttribute(IFRAME_ATTRIBUTES[i]);
|
|
269
|
+
if (value !== null) {
|
|
270
|
+
iframe.setAttribute(IFRAME_ATTRIBUTES[i], value);
|
|
118
271
|
}
|
|
119
272
|
}
|
|
120
273
|
} else {
|
|
@@ -126,6 +279,24 @@ export function buildIframe(html: string): HTMLIFrameElement | null {
|
|
|
126
279
|
return iframe;
|
|
127
280
|
}
|
|
128
281
|
|
|
282
|
+
/* Sanitizers
|
|
283
|
+
Two entry points, one walker: both rebuild clean DOM from an allowlist
|
|
284
|
+
so markup stored in a storymap's JSON can never execute code in a
|
|
285
|
+
viewer's browser. They differ only in what they allow.
|
|
286
|
+
================================================== */
|
|
287
|
+
|
|
288
|
+
/** What a sanitizer pass is permitted to keep. */
|
|
289
|
+
interface SanitizeRules {
|
|
290
|
+
/** Tags rebuilt as-is (with the filtered attributes). */
|
|
291
|
+
tags: readonly string[];
|
|
292
|
+
/** Tags removed together with their contents. */
|
|
293
|
+
dropTags: readonly string[];
|
|
294
|
+
/** Attributes copied verbatim (the rest are dropped). */
|
|
295
|
+
attributes: readonly string[];
|
|
296
|
+
/** Rebuild a pasted <iframe> instead of dropping it. */
|
|
297
|
+
rebuildIframes: boolean;
|
|
298
|
+
}
|
|
299
|
+
|
|
129
300
|
/* Sanitize pasted blockquote markup into a DocumentFragment.
|
|
130
301
|
Allowlisted formatting tags are kept (with all attributes stripped,
|
|
131
302
|
except a validated href on links), unknown tags are unwrapped, and
|
|
@@ -133,36 +304,149 @@ export function buildIframe(html: string): HTMLIFrameElement | null {
|
|
|
133
304
|
================================================== */
|
|
134
305
|
export function sanitizeBlockquote(html: string): DocumentFragment {
|
|
135
306
|
const fragment = document.createDocumentFragment();
|
|
136
|
-
appendSanitized(parseInert(html).body, fragment
|
|
307
|
+
appendSanitized(parseInert(html).body, fragment, {
|
|
308
|
+
tags: BLOCKQUOTE_TAGS,
|
|
309
|
+
dropTags: DROP_TAGS,
|
|
310
|
+
attributes: [],
|
|
311
|
+
rebuildIframes: false,
|
|
312
|
+
});
|
|
313
|
+
return fragment;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* Sanitize slide text (issue #358) into a DocumentFragment.
|
|
317
|
+
Allowlisted prose/media tags survive with allowlisted attributes; URL
|
|
318
|
+
attributes are validated to http(s); `style`, `id` and `name` are
|
|
319
|
+
dropped; `target` is always forced to `_blank`; and <iframe> embeds are
|
|
320
|
+
rebuilt via buildIframe() so extra media can live in the text field.
|
|
321
|
+
Anything outside the allowlist is unwrapped (its text is kept) rather
|
|
322
|
+
than dropped with its contents, so a story that used a stray tag still
|
|
323
|
+
reads correctly.
|
|
324
|
+
|
|
325
|
+
This is also the sanitizer for author-supplied *strings* that were
|
|
326
|
+
previously injected raw — media credit, media caption and the slide
|
|
327
|
+
navigation headline. It is the migration path for removed media types
|
|
328
|
+
(e.g. vine): paste the provider's iframe snippet into the slide text.
|
|
329
|
+
|
|
330
|
+
The result must be appended as a live DocumentFragment and never
|
|
331
|
+
re-serialised through innerHTML: the fragment-based build is what makes
|
|
332
|
+
the classic "reparse mXSS" unreachable here.
|
|
333
|
+
================================================== */
|
|
334
|
+
export function sanitizeSlideText(html: string): DocumentFragment {
|
|
335
|
+
const fragment = document.createDocumentFragment();
|
|
336
|
+
appendSanitized(parseInert(html).body, fragment, {
|
|
337
|
+
tags: SLIDE_TEXT_TAGS,
|
|
338
|
+
dropTags: SLIDE_TEXT_DROP_TAGS,
|
|
339
|
+
attributes: SLIDE_TEXT_ATTRIBUTES,
|
|
340
|
+
rebuildIframes: true,
|
|
341
|
+
});
|
|
137
342
|
return fragment;
|
|
138
343
|
}
|
|
139
344
|
|
|
140
|
-
|
|
345
|
+
/** True when `url` may be used as an href/src. */
|
|
346
|
+
function isSafeURL(url: string | null): url is string {
|
|
347
|
+
return validateWebURL(url) !== null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Validate a srcset-style attribute: every candidate URL must be http(s).
|
|
352
|
+
* `srcset` is a comma-separated list of "<url> <descriptor>" pairs, so the
|
|
353
|
+
* whole attribute is dropped unless *every* candidate passes.
|
|
354
|
+
*/
|
|
355
|
+
function sanitizeSrcset(value: string): string | null {
|
|
356
|
+
const candidates = value
|
|
357
|
+
.split(",")
|
|
358
|
+
.map((part) => part.trim())
|
|
359
|
+
.filter(Boolean);
|
|
360
|
+
if (candidates.length === 0) {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
const kept: string[] = [];
|
|
364
|
+
for (const candidate of candidates) {
|
|
365
|
+
const url = candidate.split(/\s+/)[0];
|
|
366
|
+
if (!isSafeURL(url)) {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
kept.push(candidate);
|
|
370
|
+
}
|
|
371
|
+
return kept.join(", ");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function appendSanitized(node: Node, parent: Node, rules: SanitizeRules): void {
|
|
141
375
|
for (let i = 0; i < node.childNodes.length; i++) {
|
|
142
376
|
const child = node.childNodes[i];
|
|
143
377
|
if (child.nodeType === 3) {
|
|
144
|
-
parent.appendChild(document.createTextNode(child.nodeValue));
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
378
|
+
parent.appendChild(document.createTextNode(child.nodeValue ?? ""));
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
if (child.nodeType !== 1) {
|
|
382
|
+
// Comments and other node types are dropped
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
const el = child as Element;
|
|
386
|
+
const tag = el.tagName.toUpperCase();
|
|
387
|
+
|
|
388
|
+
if (rules.dropTags.includes(tag)) {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (tag === "IFRAME" && rules.rebuildIframes) {
|
|
392
|
+
const clean = buildIframe(el.outerHTML);
|
|
393
|
+
if (clean) {
|
|
394
|
+
clean.setAttribute("loading", "lazy");
|
|
395
|
+
// A rebuilt embed still runs with full privileges unless it is
|
|
396
|
+
// sandboxed. This is the allowlist for what third-party embed
|
|
397
|
+
// pages can do; presentation and popups stay enabled because
|
|
398
|
+
// several legacy providers need them to work at all.
|
|
399
|
+
clean.setAttribute("sandbox", ALLOWED_IFRAME_SANDBOX);
|
|
400
|
+
clean.setAttribute("referrerpolicy", "no-referrer");
|
|
401
|
+
parent.appendChild(clean);
|
|
402
|
+
}
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (!rules.tags.includes(tag)) {
|
|
406
|
+
// Not on the allowlist: unwrap, keeping its children and text
|
|
407
|
+
appendSanitized(child, parent, rules);
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const cleanEl = document.createElement(tag);
|
|
412
|
+
for (let j = 0; j < el.attributes.length; j++) {
|
|
413
|
+
const attr = el.attributes[j];
|
|
414
|
+
const name = attr.name.toLowerCase();
|
|
415
|
+
// Belt-and-braces: `on*` and `srcdoc` are not on any allowlist,
|
|
416
|
+
// but never let one through if a list is edited carelessly.
|
|
417
|
+
if (name.startsWith("on") || name === "srcdoc") {
|
|
148
418
|
continue;
|
|
149
419
|
}
|
|
150
|
-
if (
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
if (href) {
|
|
155
|
-
el.setAttribute("href", href);
|
|
156
|
-
el.setAttribute("target", "_blank");
|
|
157
|
-
}
|
|
420
|
+
if (name === "srcset") {
|
|
421
|
+
const safe = sanitizeSrcset(attr.value);
|
|
422
|
+
if (safe) {
|
|
423
|
+
cleanEl.setAttribute("srcset", safe);
|
|
158
424
|
}
|
|
159
|
-
|
|
160
|
-
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
if (URL_ATTRIBUTES.includes(name)) {
|
|
428
|
+
const safe = validateWebURL(attr.value);
|
|
429
|
+
if (safe) {
|
|
430
|
+
cleanEl.setAttribute(attr.name, safe);
|
|
431
|
+
}
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (rules.attributes.includes(name)) {
|
|
435
|
+
cleanEl.setAttribute(attr.name, attr.value);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
if (tag === "A") {
|
|
439
|
+
// Always overwritten, never inherited from the pasted markup: a
|
|
440
|
+
// `target="_top"` would navigate the host page out of the viewer.
|
|
441
|
+
if (cleanEl.hasAttribute("href")) {
|
|
442
|
+
cleanEl.setAttribute("target", "_blank");
|
|
443
|
+
cleanEl.setAttribute("rel", "noopener noreferrer");
|
|
161
444
|
} else {
|
|
162
|
-
//
|
|
163
|
-
|
|
445
|
+
// a link with no safe href is not a link
|
|
446
|
+
cleanEl.removeAttribute("target");
|
|
164
447
|
}
|
|
165
448
|
}
|
|
166
|
-
|
|
449
|
+
appendSanitized(child, cleanEl, rules);
|
|
450
|
+
parent.appendChild(cleanEl);
|
|
167
451
|
}
|
|
168
452
|
}
|