diff --git a/package-lock.json b/package-lock.json index 5dde684..547a947 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,18 +11,19 @@ "dependencies": { "@types/express": "^4.17.14", "@types/mongoose": "^5.11.97", - "@types/node": "^18.11.9", "@types/react-dom": "^18.0.8", "@types/ws": "^8.5.3", "express": "^4.18.2", "mongoose": "^6.7.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "reveal.js": "^5.0.5" }, "devDependencies": { "@babel/core": "^7.19.6", "@babel/preset-env": "^7.19.4", "@babel/preset-react": "^7.14.5", + "@types/node": "^20.11.25", "@types/react": "^18.0.25", "@typescript-eslint/eslint-plugin": "^5.41.0", "@typescript-eslint/parser": "^5.41.0", @@ -37,15 +38,29 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.31.10", + "html-loader": "^5.0.0", "html-webpack-plugin": "^5.5.0", "license-webpack-plugin": "^4.0.2", "style-loader": "^3.3.1", + "tailwindcss": "^3.4.1", "ts-loader": "^9.4.1", "typescript": "^4.8.4", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -2497,6 +2512,50 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -2520,9 +2579,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -2559,13 +2618,13 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@mongodb-js/saslprep": { @@ -2612,6 +2671,16 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@smithy/abort-controller": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", @@ -3249,9 +3318,12 @@ } }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/prop-types": { "version": "15.7.5", @@ -3881,6 +3953,31 @@ "node": ">=4" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4037,6 +4134,15 @@ } ] }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -4238,6 +4344,15 @@ "tslib": "^2.0.3" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001430", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001430.tgz", @@ -4268,6 +4383,42 @@ "node": ">=4" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -4278,9 +4429,9 @@ } }, "node_modules/clean-css": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", - "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", "dev": true, "dependencies": { "source-map": "~0.6.0" @@ -4606,6 +4757,12 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4618,6 +4775,12 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4704,6 +4867,12 @@ "tslib": "^2.0.3" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4715,6 +4884,12 @@ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -5545,9 +5720,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -5730,6 +5905,22 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -5752,10 +5943,27 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -5968,6 +6176,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -5977,6 +6197,68 @@ "he": "bin/he" } }, + "node_modules/html-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", + "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-loader/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/html-loader/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-loader/node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, "node_modules/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -6213,6 +6495,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -6242,12 +6536,12 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6277,6 +6571,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -6431,6 +6734,24 @@ "node": ">=0.10.0" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -6469,6 +6790,15 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -6594,6 +6924,21 @@ } } }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -6789,6 +7134,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mongodb": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.1.tgz", @@ -6865,6 +7219,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -6955,6 +7320,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -7149,6 +7523,30 @@ "node": ">=6" } }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -7200,6 +7598,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -7232,6 +7655,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -7324,6 +7765,89 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", @@ -7383,10 +7907,29 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -7574,6 +8117,27 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", @@ -7724,12 +8288,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -7780,6 +8344,14 @@ "node": ">=0.10.0" } }, + "node_modules/reveal.js": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-5.0.5.tgz", + "integrity": "sha512-MPWPV/cRlkZhh72dAGYv/bUCr9ulwM2/ucCqiL/KN4tvhb6VvN49iwOyWHE08wppj8lMQXi2xbS3kyKgfyTYqg==", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -8046,6 +8618,18 @@ "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -8122,6 +8706,71 @@ "node": ">= 0.8" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -8181,6 +8830,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -8224,6 +8886,97 @@ "webpack": "^5.0.0" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -8248,6 +9001,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwindcss": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -8339,6 +9129,27 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -8379,6 +9190,12 @@ "node": ">=12" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/ts-loader": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.1.tgz", @@ -8598,6 +9415,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -8940,6 +9762,133 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8952,6 +9901,18 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -8966,6 +9927,12 @@ } }, "dependencies": { + "@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true + }, "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -10799,6 +11766,37 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -10816,9 +11814,9 @@ "dev": true }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true }, "@jridgewell/source-map": { @@ -10851,13 +11849,13 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@mongodb-js/saslprep": { @@ -10895,6 +11893,13 @@ "fastq": "^1.6.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, "@smithy/abort-controller": { "version": "2.0.12", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", @@ -11429,9 +12434,12 @@ } }, "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/prop-types": { "version": "15.7.5", @@ -11912,6 +12920,28 @@ "color-convert": "^1.9.0" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -12017,6 +13047,12 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, "body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -12167,6 +13203,12 @@ "tslib": "^2.0.3" } }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, "caniuse-lite": { "version": "1.0.30001430", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001430.tgz", @@ -12184,6 +13226,33 @@ "supports-color": "^5.3.0" } }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -12191,9 +13260,9 @@ "dev": true }, "clean-css": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", - "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -12424,6 +13493,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -12433,6 +13508,12 @@ "path-type": "^4.0.0" } }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -12498,6 +13579,12 @@ "tslib": "^2.0.3" } }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -12509,6 +13596,12 @@ "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", "dev": true }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -13119,9 +14212,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -13262,6 +14355,16 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -13278,10 +14381,17 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "function.prototype.name": { "version": "1.1.5", @@ -13431,12 +14541,60 @@ "has-symbols": "^1.0.2" } }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "html-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", + "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "dev": true, + "requires": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "dependencies": { + "commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + }, + "html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + } + } + } + }, "html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -13592,6 +14750,15 @@ "has-bigints": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -13609,12 +14776,12 @@ "dev": true }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "is-date-object": { @@ -13632,6 +14799,12 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -13735,6 +14908,16 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -13763,6 +14946,12 @@ } } }, + "jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true + }, "js-sdsl": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", @@ -13853,6 +15042,18 @@ "webpack-sources": "^3.0.0" } }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -13997,6 +15198,12 @@ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, "mongodb": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.1.tgz", @@ -14057,6 +15264,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -14123,6 +15341,12 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -14263,6 +15487,23 @@ "callsites": "^3.0.0" } }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "requires": { + "entities": "^4.4.0" + }, + "dependencies": { + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + } + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -14302,6 +15543,24 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true + } + } + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -14325,6 +15584,18 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -14384,6 +15655,44 @@ "source-map-js": "^1.0.2" } }, + "postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "dependencies": { + "lilconfig": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", + "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "dev": true + } + } + }, "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", @@ -14420,10 +15729,19 @@ "icss-utils": "^5.0.0" } }, + "postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.11" + } + }, "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -14555,6 +15873,24 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", @@ -14674,12 +16010,12 @@ "dev": true }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -14713,6 +16049,11 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, + "reveal.js": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/reveal.js/-/reveal.js-5.0.5.tgz", + "integrity": "sha512-MPWPV/cRlkZhh72dAGYv/bUCr9ulwM2/ucCqiL/KN4tvhb6VvN49iwOyWHE08wppj8lMQXi2xbS3kyKgfyTYqg==" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -14913,6 +16254,12 @@ "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -14969,6 +16316,53 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + } + } + }, "string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -15016,6 +16410,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -15041,6 +16444,71 @@ "dev": true, "requires": {} }, + "sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -15056,6 +16524,36 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "tailwindcss": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.1.tgz", + "integrity": "sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==", + "dev": true, + "requires": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + } + }, "tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -15114,6 +16612,24 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -15142,6 +16658,12 @@ "punycode": "^2.1.1" } }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "ts-loader": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.1.tgz", @@ -15302,6 +16824,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -15529,6 +17056,94 @@ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -15541,6 +17156,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "dev": true + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 46db6e0..2336177 100644 --- a/package.json +++ b/package.json @@ -17,18 +17,19 @@ "dependencies": { "@types/express": "^4.17.14", "@types/mongoose": "^5.11.97", - "@types/node": "^18.11.9", "@types/react-dom": "^18.0.8", "@types/ws": "^8.5.3", "express": "^4.18.2", "mongoose": "^6.7.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "reveal.js": "^5.0.5" }, "devDependencies": { "@babel/core": "^7.19.6", "@babel/preset-env": "^7.19.4", "@babel/preset-react": "^7.14.5", + "@types/node": "^20.11.25", "@types/react": "^18.0.25", "@typescript-eslint/eslint-plugin": "^5.41.0", "@typescript-eslint/parser": "^5.41.0", @@ -43,12 +44,14 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-promise": "^6.1.1", "eslint-plugin-react": "^7.31.10", + "html-loader": "^5.0.0", "html-webpack-plugin": "^5.5.0", "license-webpack-plugin": "^4.0.2", "style-loader": "^3.3.1", + "tailwindcss": "^3.4.1", "ts-loader": "^9.4.1", "typescript": "^4.8.4", "webpack": "^5.74.0", "webpack-cli": "^4.10.0" } -} \ No newline at end of file +} diff --git a/src/public/assets/css/styles.css b/src/public/assets/css/styles.css index 4397c4a..482d78b 100644 --- a/src/public/assets/css/styles.css +++ b/src/public/assets/css/styles.css @@ -1,4 +1,8 @@ /* Global CSS Properties */ +@tailwind base; +@tailwind components; +@tailwind utilities; + :root { --main: #00629b; --accent: #ffcd00; diff --git a/src/public/bash.tsx b/src/public/bash.tsx index 5b2556c..372b6ab 100644 --- a/src/public/bash.tsx +++ b/src/public/bash.tsx @@ -7,6 +7,7 @@ import DefaultSection from "./components/DefaultSection"; import InvolveBox from "./components/InvolveBox"; import SocialCard from "./components/SocialCard"; import Footer from "./components/Footer"; +var bashSlides = require("./bash/index.html"); class Main extends React.Component { constructor() { @@ -15,7 +16,7 @@ class Main extends React.Component { } public render() { - return

Hello World

; + return ; } } diff --git a/src/public/bash/POSIX-standard-2017.png b/src/public/bash/POSIX-standard-2017.png new file mode 100644 index 0000000..5d79128 Binary files /dev/null and b/src/public/bash/POSIX-standard-2017.png differ diff --git a/src/public/bash/css/layout.scss b/src/public/bash/css/layout.scss new file mode 100644 index 0000000..f499fdd --- /dev/null +++ b/src/public/bash/css/layout.scss @@ -0,0 +1,69 @@ +/** + * Layout helpers. + */ + +// Stretch an element vertically based on available space +.reveal .stretch, +.reveal .r-stretch { + max-width: none; + max-height: none; +} + +.reveal pre.stretch code, +.reveal pre.r-stretch code { + height: 100%; + max-height: 100%; + box-sizing: border-box; +} + +// Text that auto-fits its container +.reveal .r-fit-text { + display: inline-block; // https://github.com/rikschennink/fitty#performance + white-space: nowrap; +} + +// Stack multiple elements on top of each other +.reveal .r-stack { + display: grid; +} + +.reveal .r-stack > * { + grid-area: 1/1; + margin: auto; +} + +// Horizontal and vertical stacks +.reveal .r-vstack, +.reveal .r-hstack { + display: flex; + + img, video { + min-width: 0; + min-height: 0; + object-fit: contain; + } +} + +.reveal .r-vstack { + flex-direction: column; + align-items: center; + justify-content: center; +} + +.reveal .r-hstack { + flex-direction: row; + align-items: center; + justify-content: center; +} + +// Naming based on tailwindcss +.reveal .items-stretch { align-items: stretch; } +.reveal .items-start { align-items: flex-start; } +.reveal .items-center { align-items: center; } +.reveal .items-end { align-items: flex-end; } + +.reveal .justify-between { justify-content: space-between; } +.reveal .justify-around { justify-content: space-around; } +.reveal .justify-start { justify-content: flex-start; } +.reveal .justify-center { justify-content: center; } +.reveal .justify-end { justify-content: flex-end; } diff --git a/src/public/bash/css/print/paper.scss b/src/public/bash/css/print/paper.scss new file mode 100644 index 0000000..32fab8a --- /dev/null +++ b/src/public/bash/css/print/paper.scss @@ -0,0 +1,166 @@ + +@media print { + html:not(.print-pdf) { + overflow: visible; + width: auto; + height: auto; + + body { + margin: 0; + padding: 0; + overflow: visible; + } + } + + html:not(.print-pdf) .reveal { + background: #fff; + font-size: 20pt; + + .controls, + .state-background, + .progress, + .backgrounds, + .slide-number { + display: none !important; + } + + p, td, li { + font-size: 20pt!important; + color: #000; + } + + h1,h2,h3,h4,h5,h6 { + color: #000!important; + height: auto; + line-height: normal; + text-align: left; + letter-spacing: normal; + } + + h1 { font-size: 28pt !important; } + h2 { font-size: 24pt !important; } + h3 { font-size: 22pt !important; } + h4 { font-size: 22pt !important; font-variant: small-caps; } + h5 { font-size: 21pt !important; } + h6 { font-size: 20pt !important; font-style: italic; } + + a:link, + a:visited { + color: #000 !important; + font-weight: bold; + text-decoration: underline; + } + + ul, ol, div, p { + visibility: visible; + position: static; + width: auto; + height: auto; + display: block; + overflow: visible; + margin: 0; + text-align: left !important; + } + pre, + table { + margin-left: 0; + margin-right: 0; + } + pre code { + padding: 20px; + } + blockquote { + margin: 20px 0; + } + + .slides { + position: static !important; + width: auto !important; + height: auto !important; + + left: 0 !important; + top: 0 !important; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 0 !important; + zoom: 1 !important; + transform: none !important; + + overflow: visible !important; + display: block !important; + + text-align: left !important; + perspective: none; + + perspective-origin: 50% 50%; + } + .slides section { + visibility: visible !important; + position: static !important; + width: auto !important; + height: auto !important; + display: block !important; + overflow: visible !important; + + left: 0 !important; + top: 0 !important; + margin-left: 0 !important; + margin-top: 0 !important; + padding: 60px 20px !important; + z-index: auto !important; + + opacity: 1 !important; + + page-break-after: always !important; + + transform-style: flat !important; + transform: none !important; + transition: none !important; + } + .slides section.stack { + padding: 0 !important; + } + .slides section:last-of-type { + page-break-after: avoid !important; + } + .slides section .fragment { + opacity: 1 !important; + visibility: visible !important; + + transform: none !important; + } + + .r-fit-text { + white-space: normal !important; + } + + section img { + display: block; + margin: 15px 0px; + background: rgba(255,255,255,1); + border: 1px solid #666; + box-shadow: none; + } + + section small { + font-size: 0.8em; + } + + .hljs { + max-height: 100%; + white-space: pre-wrap; + word-wrap: break-word; + word-break: break-word; + font-size: 15pt; + } + + .hljs .hljs-ln-numbers { + white-space: nowrap; + } + + .hljs td { + font-size: inherit !important; + color: inherit !important; + } + } +} diff --git a/src/public/bash/css/print/pdf.scss b/src/public/bash/css/print/pdf.scss new file mode 100644 index 0000000..0a1c2bf --- /dev/null +++ b/src/public/bash/css/print/pdf.scss @@ -0,0 +1,159 @@ +/** + * This stylesheet is used to print reveal.js + * presentations to PDF. + * + * https://revealjs.com/pdf-export/ + */ + +html.reveal-print { + * { + -webkit-print-color-adjust: exact; + } + + & { + width: 100%; + height: 100%; + overflow: visible; + } + + body { + margin: 0 auto !important; + border: 0; + padding: 0; + float: none !important; + overflow: visible; + } + + /* Remove any elements not needed in print. */ + .nestedarrow, + .reveal .controls, + .reveal .progress, + .reveal .playback, + .reveal.overview, + .state-background { + display: none !important; + } + + .reveal pre code { + overflow: hidden !important; + } + + .reveal { + width: auto !important; + height: auto !important; + overflow: hidden !important; + } + .reveal .slides { + position: static; + width: 100% !important; + height: auto !important; + zoom: 1 !important; + pointer-events: initial; + + left: auto; + top: auto; + margin: 0 !important; + padding: 0 !important; + + overflow: visible; + display: block; + + perspective: none; + perspective-origin: 50% 50%; + } + + .reveal .slides .pdf-page { + position: relative; + overflow: hidden; + z-index: 1; + + page-break-after: always; + } + + .reveal .slides .pdf-page:last-of-type { + page-break-after: avoid; + } + + .reveal .slides section { + visibility: visible !important; + display: block !important; + position: absolute !important; + + margin: 0 !important; + padding: 0 !important; + box-sizing: border-box !important; + min-height: 1px; + + opacity: 1 !important; + + transform-style: flat !important; + transform: none !important; + } + + .reveal section.stack { + position: relative !important; + margin: 0 !important; + padding: 0 !important; + page-break-after: avoid !important; + height: auto !important; + min-height: auto !important; + } + + .reveal img { + box-shadow: none; + } + + /* Slide backgrounds are placed inside of their slide when exporting to PDF */ + .reveal .backgrounds { + display: none; + } + .reveal .slide-background { + display: block !important; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: auto !important; + } + + /* Display slide speaker notes when 'showNotes' is enabled */ + .reveal.show-notes { + max-width: none; + max-height: none; + } + .reveal .speaker-notes-pdf { + display: block; + width: 100%; + height: auto; + max-height: none; + top: auto; + right: auto; + bottom: auto; + left: auto; + z-index: 100; + } + + /* Layout option which makes notes appear on a separate page */ + .reveal .speaker-notes-pdf[data-layout="separate-page"] { + position: relative; + color: inherit; + background-color: transparent; + padding: 20px; + page-break-after: always; + border: 0; + } + + /* Display slide numbers when 'slideNumber' is enabled */ + .reveal .slide-number-pdf { + display: block; + position: absolute; + font-size: 14px; + visibility: visible; + } + + /* This accessibility tool is not useful in PDF and breaks it visually */ + .aria-status { + display: none; + } +} diff --git a/src/public/bash/css/reveal.scss b/src/public/bash/css/reveal.scss new file mode 100644 index 0000000..0a3ade7 --- /dev/null +++ b/src/public/bash/css/reveal.scss @@ -0,0 +1,2109 @@ +@use "sass:math"; + +/** + * reveal.js + * http://revealjs.com + * MIT licensed + * + * Copyright (C) Hakim El Hattab, https://hakim.se + */ + +@import 'layout'; + +/********************************************* + * GLOBAL STYLES + *********************************************/ + +html.reveal-full-page { + width: 100%; + height: 100%; + height: 100vh; + height: calc( var(--vh, 1vh) * 100 ); + height: 100svh; + overflow: hidden; +} + +.reveal-viewport { + height: 100%; + overflow: hidden; + position: relative; + line-height: 1; + margin: 0; + + background-color: #fff; + color: #000; + + --r-controls-spacing: 12px; +} + +// Force the presentation to cover the full viewport when we +// enter fullscreen mode. Fixes sizing issues in Safari. +.reveal-viewport:fullscreen { + top: 0 !important; + left: 0 !important; + width: 100% !important; + height: 100% !important; + transform: none !important; +} + + +/********************************************* + * VIEW FRAGMENTS + *********************************************/ + +.reveal .fragment { + transition: all .2s ease; + + &:not(.custom) { + opacity: 0; + visibility: hidden; + will-change: opacity; + } + + &.visible { + opacity: 1; + visibility: inherit; + } + + &.disabled { + transition: none; + } +} + +.reveal .fragment.grow { + opacity: 1; + visibility: inherit; + + &.visible { + transform: scale( 1.3 ); + } +} + +.reveal .fragment.shrink { + opacity: 1; + visibility: inherit; + + &.visible { + transform: scale( 0.7 ); + } +} + +.reveal .fragment.zoom-in { + transform: scale( 0.1 ); + + &.visible { + transform: none; + } +} + +.reveal .fragment.fade-out { + opacity: 1; + visibility: inherit; + + &.visible { + opacity: 0; + visibility: hidden; + } +} + +.reveal .fragment.semi-fade-out { + opacity: 1; + visibility: inherit; + + &.visible { + opacity: 0.5; + visibility: inherit; + } +} + +.reveal .fragment.strike { + opacity: 1; + visibility: inherit; + + &.visible { + text-decoration: line-through; + } +} + +.reveal .fragment.fade-up { + transform: translate(0, 40px); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .fragment.fade-down { + transform: translate(0, -40px); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .fragment.fade-right { + transform: translate(-40px, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .fragment.fade-left { + transform: translate(40px, 0); + + &.visible { + transform: translate(0, 0); + } +} + +.reveal .fragment.fade-in-then-out, +.reveal .fragment.current-visible { + opacity: 0; + visibility: hidden; + + &.current-fragment { + opacity: 1; + visibility: inherit; + } +} + +.reveal .fragment.fade-in-then-semi-out { + opacity: 0; + visibility: hidden; + + &.visible { + opacity: 0.5; + visibility: inherit; + } + + &.current-fragment { + opacity: 1; + visibility: inherit; + } +} + +.reveal .fragment.highlight-red, +.reveal .fragment.highlight-current-red, +.reveal .fragment.highlight-green, +.reveal .fragment.highlight-current-green, +.reveal .fragment.highlight-blue, +.reveal .fragment.highlight-current-blue { + opacity: 1; + visibility: inherit; +} + .reveal .fragment.highlight-red.visible { + color: #ff2c2d + } + .reveal .fragment.highlight-green.visible { + color: #17ff2e; + } + .reveal .fragment.highlight-blue.visible { + color: #1b91ff; + } + +.reveal .fragment.highlight-current-red.current-fragment { + color: #ff2c2d +} +.reveal .fragment.highlight-current-green.current-fragment { + color: #17ff2e; +} +.reveal .fragment.highlight-current-blue.current-fragment { + color: #1b91ff; +} + + +/********************************************* + * DEFAULT ELEMENT STYLES + *********************************************/ + +/* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */ +.reveal:after { + content: ''; + font-style: italic; +} + +.reveal iframe { + z-index: 1; +} + +/** Prevents layering issues in certain browser/transition combinations */ +.reveal a { + position: relative; +} + + +/********************************************* + * CONTROLS + *********************************************/ + +@keyframes bounce-right { + 0%, 10%, 25%, 40%, 50% {transform: translateX(0);} + 20% {transform: translateX(10px);} + 30% {transform: translateX(-5px);} +} + +@keyframes bounce-left { + 0%, 10%, 25%, 40%, 50% {transform: translateX(0);} + 20% {transform: translateX(-10px);} + 30% {transform: translateX(5px);} +} + +@keyframes bounce-down { + 0%, 10%, 25%, 40%, 50% {transform: translateY(0);} + 20% {transform: translateY(10px);} + 30% {transform: translateY(-5px);} +} + +$controlArrowSize: 3.6em; +$controlArrowSpacing: 1.4em; +$controlArrowLength: 2.6em; +$controlArrowThickness: 0.5em; +$controlsArrowAngle: 45deg; +$controlsArrowAngleHover: 40deg; +$controlsArrowAngleActive: 36deg; + +@mixin controlsArrowTransform( $angle ) { + &:before { + transform: translateX(($controlArrowSize - $controlArrowLength)*0.5) translateY(($controlArrowSize - $controlArrowThickness)*0.5) rotate( $angle ); + } + + &:after { + transform: translateX(($controlArrowSize - $controlArrowLength)*0.5) translateY(($controlArrowSize - $controlArrowThickness)*0.5) rotate( -$angle ); + } +} + +.reveal .controls { + display: none; + position: absolute; + top: auto; + bottom: var(--r-controls-spacing); + right: var(--r-controls-spacing); + left: auto; + z-index: 11; + color: #000; + pointer-events: none; + font-size: 10px; + + button { + position: absolute; + padding: 0; + background-color: transparent; + border: 0; + outline: 0; + cursor: pointer; + color: currentColor; + transform: scale(.9999); + transition: color 0.2s ease, + opacity 0.2s ease, + transform 0.2s ease; + z-index: 2; // above slides + pointer-events: auto; + font-size: inherit; + + visibility: hidden; + opacity: 0; + + -webkit-appearance: none; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); + } + + .controls-arrow:before, + .controls-arrow:after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: $controlArrowLength; + height: $controlArrowThickness; + border-radius: $controlArrowThickness*0.5; + background-color: currentColor; + + transition: all 0.15s ease, background-color 0.8s ease; + transform-origin: math.div(floor(($controlArrowThickness*0.5)*10), 10) 50%; + will-change: transform; + } + + .controls-arrow { + position: relative; + width: $controlArrowSize; + height: $controlArrowSize; + + @include controlsArrowTransform( $controlsArrowAngle ); + + &:hover { + @include controlsArrowTransform( $controlsArrowAngleHover ); + } + + &:active { + @include controlsArrowTransform( $controlsArrowAngleActive ); + } + } + + .navigate-left { + right: $controlArrowSize + $controlArrowSpacing*2; + bottom: $controlArrowSpacing + $controlArrowSize*0.5; + transform: translateX( -10px ); + + &.highlight { + animation: bounce-left 2s 50 both ease-out; + } + } + + .navigate-right { + right: 0; + bottom: $controlArrowSpacing + $controlArrowSize*0.5; + transform: translateX( 10px ); + + .controls-arrow { + transform: rotate( 180deg ); + } + + &.highlight { + animation: bounce-right 2s 50 both ease-out; + } + } + + .navigate-up { + right: $controlArrowSpacing + $controlArrowSize*0.5; + bottom: $controlArrowSpacing*2 + $controlArrowSize; + transform: translateY( -10px ); + + .controls-arrow { + transform: rotate( 90deg ); + } + } + + .navigate-down { + right: $controlArrowSpacing + $controlArrowSize*0.5; + bottom: -$controlArrowSpacing; + padding-bottom: $controlArrowSpacing; + transform: translateY( 10px ); + + .controls-arrow { + transform: rotate( -90deg ); + } + + &.highlight { + animation: bounce-down 2s 50 both ease-out; + } + } + + // Back arrow style: "faded": + // Deemphasize backwards navigation arrows in favor of drawing + // attention to forwards navigation + &[data-controls-back-arrows="faded"] .navigate-up.enabled { + opacity: 0.3; + + &:hover { + opacity: 1; + } + } + + // Back arrow style: "hidden": + // Never show arrows for backwards navigation + &[data-controls-back-arrows="hidden"] .navigate-up.enabled { + opacity: 0; + visibility: hidden; + } + + // Any control button that can be clicked is "enabled" + .enabled { + visibility: visible; + opacity: 0.9; + cursor: pointer; + transform: none; + } + + // Any control button that leads to showing or hiding + // a fragment + .enabled.fragmented { + opacity: 0.5; + } + + .enabled:hover, + .enabled.fragmented:hover { + opacity: 1; + } +} + +.reveal:not(.rtl) .controls { + // Back arrow style: "faded": + // Deemphasize left arrow + &[data-controls-back-arrows="faded"] .navigate-left.enabled { + opacity: 0.3; + + &:hover { + opacity: 1; + } + } + + // Back arrow style: "hidden": + // Never show left arrow + &[data-controls-back-arrows="hidden"] .navigate-left.enabled { + opacity: 0; + visibility: hidden; + } +} + +.reveal.rtl .controls { + // Back arrow style: "faded": + // Deemphasize right arrow in RTL mode + &[data-controls-back-arrows="faded"] .navigate-right.enabled { + opacity: 0.3; + + &:hover { + opacity: 1; + } + } + + // Back arrow style: "hidden": + // Never show right arrow in RTL mode + &[data-controls-back-arrows="hidden"] .navigate-right.enabled { + opacity: 0; + visibility: hidden; + } +} + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-up, +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-down { + display: none; +} + +// Adjust the layout when there are no vertical slides +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-left, +.reveal:not(.has-vertical-slides) .controls .navigate-left { + bottom: $controlArrowSpacing; + right: 0.5em + $controlArrowSpacing + $controlArrowSize; +} + +.reveal[data-navigation-mode="linear"].has-horizontal-slides .navigate-right, +.reveal:not(.has-vertical-slides) .controls .navigate-right { + bottom: $controlArrowSpacing; + right: 0.5em; +} + +// Adjust the layout when there are no horizontal slides +.reveal:not(.has-horizontal-slides) .controls .navigate-up { + right: $controlArrowSpacing; + bottom: $controlArrowSpacing + $controlArrowSize; +} +.reveal:not(.has-horizontal-slides) .controls .navigate-down { + right: $controlArrowSpacing; + bottom: 0.5em; +} + +// Invert arrows based on background color +.reveal.has-dark-background .controls { + color: #fff; +} +.reveal.has-light-background .controls { + color: #000; +} + +// Disable active states on touch devices +.reveal.no-hover .controls .controls-arrow:hover, +.reveal.no-hover .controls .controls-arrow:active { + @include controlsArrowTransform( $controlsArrowAngle ); +} + +// Edge aligned controls layout +@media screen and (min-width: 500px) { + + .reveal-viewport { + --r-controls-spacing: 0.8em; + } + + .reveal .controls[data-controls-layout="edges"] { + & { + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .navigate-left, + .navigate-right, + .navigate-up, + .navigate-down { + bottom: auto; + right: auto; + } + + .navigate-left { + top: 50%; + left: var(--r-controls-spacing); + margin-top: -$controlArrowSize*0.5; + } + + .navigate-right { + top: 50%; + right: var(--r-controls-spacing); + margin-top: -$controlArrowSize*0.5; + } + + .navigate-up { + top: var(--r-controls-spacing); + left: 50%; + margin-left: -$controlArrowSize*0.5; + } + + .navigate-down { + bottom: calc(var(--r-controls-spacing) - #{$controlArrowSpacing} + 0.3em); + left: 50%; + margin-left: -$controlArrowSize*0.5; + } + } + +} + + +/********************************************* + * PROGRESS BAR + *********************************************/ + +.reveal .progress { + position: absolute; + display: none; + height: 3px; + width: 100%; + bottom: 0; + left: 0; + z-index: 10; + + background-color: rgba( 0, 0, 0, 0.2 ); + color: #fff; +} + .reveal .progress:after { + content: ''; + display: block; + position: absolute; + height: 10px; + width: 100%; + top: -10px; + } + .reveal .progress span { + display: block; + height: 100%; + width: 100%; + + background-color: currentColor; + transition: transform 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + transform-origin: 0 0; + transform: scaleX(0); + } + +/********************************************* + * SLIDE NUMBER + *********************************************/ + +.reveal .slide-number { + position: absolute; + display: block; + right: 8px; + bottom: 8px; + z-index: 31; + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 1; + color: #fff; + background-color: rgba( 0, 0, 0, 0.4 ); + padding: 5px; +} + +.reveal .slide-number a { + color: currentColor; +} + +.reveal .slide-number-delimiter { + margin: 0 3px; +} + +/********************************************* + * SLIDES + *********************************************/ + +.reveal { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + touch-action: pinch-zoom; +} + +// Swiping on an embedded deck should not block page scrolling +.reveal.embedded { + touch-action: pan-y; +} + +.reveal .slides { + position: absolute; + width: 100%; + height: 100%; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + pointer-events: none; + + overflow: visible; + z-index: 1; + text-align: center; + perspective: 600px; + perspective-origin: 50% 40%; +} + +.reveal .slides>section { + perspective: 600px; +} + +.reveal .slides>section, +.reveal .slides>section>section { + display: none; + position: absolute; + width: 100%; + pointer-events: auto; + + z-index: 10; + transform-style: flat; + transition: transform-origin 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + transform 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + visibility 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985), + opacity 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); +} + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"] .slides section { + transition-duration: 400ms; +} +.reveal[data-transition-speed="slow"] .slides section { + transition-duration: 1200ms; +} + +/* Slide-specific transition speed overrides */ +.reveal .slides section[data-transition-speed="fast"] { + transition-duration: 400ms; +} +.reveal .slides section[data-transition-speed="slow"] { + transition-duration: 1200ms; +} + +.reveal .slides>section.stack { + padding-top: 0; + padding-bottom: 0; + pointer-events: none; + height: 100%; +} + +.reveal .slides>section.present, +.reveal .slides>section>section.present { + display: block; + z-index: 11; + opacity: 1; +} + +.reveal .slides>section:empty, +.reveal .slides>section>section:empty, +.reveal .slides>section[data-background-interactive], +.reveal .slides>section>section[data-background-interactive] { + pointer-events: none; +} + +.reveal.center, +.reveal.center .slides, +.reveal.center .slides section { + min-height: 0 !important; +} + +/* Don't allow interaction with invisible slides */ +.reveal .slides>section:not(.present), +.reveal .slides>section>section:not(.present) { + pointer-events: none; +} + +.reveal.overview .slides>section, +.reveal.overview .slides>section>section { + pointer-events: auto; +} + +.reveal .slides>section.past, +.reveal .slides>section.future, +.reveal .slides>section.past>section, +.reveal .slides>section.future>section, +.reveal .slides>section>section.past, +.reveal .slides>section>section.future { + opacity: 0; +} + + +/********************************************* + * Mixins for readability of transitions + *********************************************/ + +@mixin transition-global($style) { + .reveal .slides section[data-transition=#{$style}], + .reveal.#{$style} .slides section:not([data-transition]) { + @content; + } +} +@mixin transition-stack($style) { + .reveal .slides section[data-transition=#{$style}].stack, + .reveal.#{$style} .slides section.stack { + @content; + } +} +@mixin transition-horizontal-past($style) { + .reveal .slides>section[data-transition=#{$style}].past, + .reveal .slides>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section:not([data-transition]).past { + @content; + } +} +@mixin transition-horizontal-future($style) { + .reveal .slides>section[data-transition=#{$style}].future, + .reveal .slides>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section:not([data-transition]).future { + @content; + } +} + +@mixin transition-vertical-past($style) { + .reveal .slides>section>section[data-transition=#{$style}].past, + .reveal .slides>section>section[data-transition~=#{$style}-out].past, + .reveal.#{$style} .slides>section>section:not([data-transition]).past { + @content; + } +} +@mixin transition-vertical-future($style) { + .reveal .slides>section>section[data-transition=#{$style}].future, + .reveal .slides>section>section[data-transition~=#{$style}-in].future, + .reveal.#{$style} .slides>section>section:not([data-transition]).future { + @content; + } +} + +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ + +@each $stylename in slide, linear { + @include transition-horizontal-past(#{$stylename}) { + transform: translate(-150%, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate(150%, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate(0, -150%); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate(0, 150%); + } +} + +/********************************************* + * CONVEX TRANSITION + * Aliased 'default' for backwards compatibility + *********************************************/ + +@each $stylename in default, convex { + @include transition-stack(#{$stylename}) { + transform-style: preserve-3d; + } + + @include transition-horizontal-past(#{$stylename}) { + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + } + @include transition-horizontal-future(#{$stylename}) { + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + } + @include transition-vertical-past(#{$stylename}) { + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + } + @include transition-vertical-future(#{$stylename}) { + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + } +} + +/********************************************* + * CONCAVE TRANSITION + *********************************************/ + +@include transition-stack(concave) { + transform-style: preserve-3d; +} + +@include transition-horizontal-past(concave) { + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); +} +@include transition-horizontal-future(concave) { + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); +} +@include transition-vertical-past(concave) { + transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); +} +@include transition-vertical-future(concave) { + transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); +} + + +/********************************************* + * ZOOM TRANSITION + *********************************************/ + +@include transition-global(zoom) { + transition-timing-function: ease; +} +@include transition-horizontal-past(zoom) { + visibility: hidden; + transform: scale(16); +} +@include transition-horizontal-future(zoom) { + visibility: hidden; + transform: scale(0.2); +} +@include transition-vertical-past(zoom) { + transform: scale(16); +} +@include transition-vertical-future(zoom) { + transform: scale(0.2); +} + + +/********************************************* + * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ + +.reveal.cube .slides { + perspective: 1300px; +} + +.reveal.cube .slides section { + padding: 30px; + min-height: 700px; + backface-visibility: hidden; + box-sizing: border-box; + transform-style: preserve-3d; +} + .reveal.center.cube .slides section { + min-height: 0; + } + .reveal.cube .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0,0,0,0.1); + border-radius: 4px; + transform: translateZ( -20px ); + } + .reveal.cube .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0,0,0,0.2); + transform: translateZ(-90px) rotateX( 65deg ); + } + +.reveal.cube .slides>section.stack { + padding: 0; + background: none; +} + +.reveal.cube .slides>section.past { + transform-origin: 100% 0%; + transform: translate3d(-100%, 0, 0) rotateY(-90deg); +} + +.reveal.cube .slides>section.future { + transform-origin: 0% 0%; + transform: translate3d(100%, 0, 0) rotateY(90deg); +} + +.reveal.cube .slides>section>section.past { + transform-origin: 0% 100%; + transform: translate3d(0, -100%, 0) rotateX(90deg); +} + +.reveal.cube .slides>section>section.future { + transform-origin: 0% 0%; + transform: translate3d(0, 100%, 0) rotateX(-90deg); +} + + +/********************************************* + * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ + +.reveal.page .slides { + perspective-origin: 0% 50%; + perspective: 3000px; +} + +.reveal.page .slides section { + padding: 30px; + min-height: 700px; + box-sizing: border-box; + transform-style: preserve-3d; +} + .reveal.page .slides section.past { + z-index: 12; + } + .reveal.page .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0,0,0,0.1); + transform: translateZ( -20px ); + } + .reveal.page .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0,0,0,0.2); + + -webkit-transform: translateZ(-90px) rotateX( 65deg ); + } + +.reveal.page .slides>section.stack { + padding: 0; + background: none; +} + +.reveal.page .slides>section.past { + transform-origin: 0% 0%; + transform: translate3d(-40%, 0, 0) rotateY(-80deg); +} + +.reveal.page .slides>section.future { + transform-origin: 100% 0%; + transform: translate3d(0, 0, 0); +} + +.reveal.page .slides>section>section.past { + transform-origin: 0% 0%; + transform: translate3d(0, -40%, 0) rotateX(80deg); +} + +.reveal.page .slides>section>section.future { + transform-origin: 0% 100%; + transform: translate3d(0, 0, 0); +} + + +/********************************************* + * FADE TRANSITION + *********************************************/ + +.reveal .slides section[data-transition=fade], +.reveal.fade .slides section:not([data-transition]), +.reveal.fade .slides>section>section:not([data-transition]) { + transform: none; + transition: opacity 0.5s; +} + + +.reveal.fade.overview .slides section, +.reveal.fade.overview .slides>section>section { + transition: none; +} + + +/********************************************* + * NO TRANSITION + *********************************************/ + +@include transition-global(none) { + transform: none; + transition: none; +} + + +/********************************************* + * PAUSED MODE + *********************************************/ + +.reveal .pause-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: black; + visibility: hidden; + opacity: 0; + z-index: 100; + transition: all 1s ease; +} + +.reveal .pause-overlay .resume-button { + position: absolute; + bottom: 20px; + right: 20px; + color: #ccc; + border-radius: 2px; + padding: 6px 14px; + border: 2px solid #ccc; + font-size: 16px; + background: transparent; + cursor: pointer; + + &:hover { + color: #fff; + border-color: #fff; + } +} + +.reveal.paused .pause-overlay { + visibility: visible; + opacity: 1; +} + + +/********************************************* + * FALLBACK + *********************************************/ + +.reveal .no-transition, +.reveal .no-transition *, +.reveal .slides.disable-slide-transitions section { + transition: none !important; +} + +.reveal .slides.disable-slide-transitions section { + transform: none !important; +} + + +/********************************************* + * PER-SLIDE BACKGROUNDS + *********************************************/ + +.reveal .backgrounds { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + perspective: 600px; +} + .reveal .slide-background { + display: none; + position: absolute; + width: 100%; + height: 100%; + opacity: 0; + visibility: hidden; + overflow: hidden; + + background-color: rgba( 0, 0, 0, 0 ); + + transition: all 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985); + } + + .reveal .slide-background-content { + position: absolute; + width: 100%; + height: 100%; + + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + + .reveal .slide-background.stack { + display: block; + } + + .reveal .slide-background.present { + opacity: 1; + visibility: visible; + z-index: 2; + } + + .print-pdf .reveal .slide-background { + opacity: 1 !important; + visibility: visible !important; + } + +/* Video backgrounds */ +.reveal .slide-background video { + position: absolute; + width: 100%; + height: 100%; + max-width: none; + max-height: none; + top: 0; + left: 0; + object-fit: cover; +} + .reveal .slide-background[data-background-size="contain"] video { + object-fit: contain; + } + +/* Immediate transition style */ +.reveal[data-background-transition=none]>.backgrounds .slide-background:not([data-background-transition]), +.reveal>.backgrounds .slide-background[data-background-transition=none] { + transition: none; +} + +/* Slide */ +.reveal[data-background-transition=slide]>.backgrounds .slide-background:not([data-background-transition]), +.reveal>.backgrounds .slide-background[data-background-transition=slide] { + opacity: 1; +} + .reveal[data-background-transition=slide]>.backgrounds .slide-background.past:not([data-background-transition]), + .reveal>.backgrounds .slide-background.past[data-background-transition=slide] { + transform: translate(-100%, 0); + } + .reveal[data-background-transition=slide]>.backgrounds .slide-background.future:not([data-background-transition]), + .reveal>.backgrounds .slide-background.future[data-background-transition=slide] { + transform: translate(100%, 0); + } + + .reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]), + .reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide] { + transform: translate(0, -100%); + } + .reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]), + .reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide] { + transform: translate(0, 100%); + } + + +/* Convex */ +.reveal[data-background-transition=convex]>.backgrounds .slide-background.past:not([data-background-transition]), +.reveal>.backgrounds .slide-background.past[data-background-transition=convex] { + opacity: 0; + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); +} +.reveal[data-background-transition=convex]>.backgrounds .slide-background.future:not([data-background-transition]), +.reveal>.backgrounds .slide-background.future[data-background-transition=convex] { + opacity: 0; + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); +} + +.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]), +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=convex] { + opacity: 0; + transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); +} +.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]), +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=convex] { + opacity: 0; + transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); +} + + +/* Concave */ +.reveal[data-background-transition=concave]>.backgrounds .slide-background.past:not([data-background-transition]), +.reveal>.backgrounds .slide-background.past[data-background-transition=concave] { + opacity: 0; + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); +} +.reveal[data-background-transition=concave]>.backgrounds .slide-background.future:not([data-background-transition]), +.reveal>.backgrounds .slide-background.future[data-background-transition=concave] { + opacity: 0; + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); +} + +.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]), +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=concave] { + opacity: 0; + transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); +} +.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]), +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=concave] { + opacity: 0; + transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); +} + +/* Zoom */ +.reveal[data-background-transition=zoom]>.backgrounds .slide-background:not([data-background-transition]), +.reveal>.backgrounds .slide-background[data-background-transition=zoom] { + transition-timing-function: ease; +} + +.reveal[data-background-transition=zoom]>.backgrounds .slide-background.past:not([data-background-transition]), +.reveal>.backgrounds .slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(16); +} +.reveal[data-background-transition=zoom]>.backgrounds .slide-background.future:not([data-background-transition]), +.reveal>.backgrounds .slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(0.2); +} + +.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]), +.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(16); +} +.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]), +.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=zoom] { + opacity: 0; + visibility: hidden; + transform: scale(0.2); +} + + +/* Global transition speed settings */ +.reveal[data-transition-speed="fast"]>.backgrounds .slide-background { + transition-duration: 400ms; +} +.reveal[data-transition-speed="slow"]>.backgrounds .slide-background { + transition-duration: 1200ms; +} + + +/********************************************* + * AUTO ANIMATE + *********************************************/ + +.reveal [data-auto-animate-target^="unmatched"] { + will-change: opacity; +} + +.reveal section[data-auto-animate]:not(.stack):not([data-auto-animate="running"]) [data-auto-animate-target^="unmatched"] { + opacity: 0; +} + + +/********************************************* + * OVERVIEW + *********************************************/ + +.reveal.overview { + perspective-origin: 50% 50%; + perspective: 700px; + + .slides { + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + + .slides section { + height: 100%; + top: 0 !important; + opacity: 1 !important; + overflow: hidden; + visibility: visible !important; + cursor: pointer; + box-sizing: border-box; + } + .slides section:hover, + .slides section.present { + outline: 10px solid rgba(150,150,150,0.4); + outline-offset: 10px; + } + .slides section .fragment { + opacity: 1; + transition: none; + } + .slides section:after, + .slides section:before { + display: none !important; + } + .slides>section.stack { + padding: 0; + top: 0 !important; + background: none; + outline: none; + overflow: visible; + } + + .backgrounds { + perspective: inherit; + + // Fixes overview rendering errors in FF48+, not applied to + // other browsers since it degrades performance + -moz-transform-style: preserve-3d; + } + + .backgrounds .slide-background { + opacity: 1; + visibility: visible; + + // This can't be applied to the slide itself in Safari + outline: 10px solid rgba(150,150,150,0.1); + outline-offset: 10px; + } + + .backgrounds .slide-background.stack { + overflow: visible; + } +} + +// Disable transitions transitions while we're activating +// or deactivating the overview mode. +.reveal.overview .slides section, +.reveal.overview-deactivating .slides section { + transition: none; +} + +.reveal.overview .backgrounds .slide-background, +.reveal.overview-deactivating .backgrounds .slide-background { + transition: none; +} + + +/********************************************* + * RTL SUPPORT + *********************************************/ + +.reveal.rtl .slides, +.reveal.rtl .slides h1, +.reveal.rtl .slides h2, +.reveal.rtl .slides h3, +.reveal.rtl .slides h4, +.reveal.rtl .slides h5, +.reveal.rtl .slides h6 { + direction: rtl; + font-family: sans-serif; +} + +.reveal.rtl pre, +.reveal.rtl code { + direction: ltr; +} + +.reveal.rtl ol, +.reveal.rtl ul { + text-align: right; +} + +.reveal.rtl .progress span { + transform-origin: 100% 0; +} + +/********************************************* + * PARALLAX BACKGROUND + *********************************************/ + +.reveal.has-parallax-background .backgrounds { + transition: all 0.8s ease; +} + +/* Global transition speed settings */ +.reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds { + transition-duration: 400ms; +} +.reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds { + transition-duration: 1200ms; +} + + +/********************************************* + * OVERLAY FOR LINK PREVIEWS AND HELP + *********************************************/ + +$overlayHeaderHeight: 40px; +$overlayHeaderPadding: 5px; + +.reveal > .overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba( 0, 0, 0, 0.95 ); + backdrop-filter: blur( 6px ); + transition: all 0.3s ease; +} + + .reveal > .overlay .spinner { + position: absolute; + display: block; + top: 50%; + left: 50%; + width: 32px; + height: 32px; + margin: -16px 0 0 -16px; + z-index: 10; + background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D); + + visibility: visible; + opacity: 0.6; + transition: all 0.3s ease; + } + + .reveal > .overlay header { + position: absolute; + left: 0; + top: 0; + width: 100%; + padding: $overlayHeaderPadding; + z-index: 2; + box-sizing: border-box; + } + .reveal > .overlay header a { + display: inline-block; + width: $overlayHeaderHeight; + height: $overlayHeaderHeight; + line-height: 36px; + padding: 0 10px; + float: right; + opacity: 0.6; + + box-sizing: border-box; + } + .reveal > .overlay header a:hover { + opacity: 1; + } + .reveal > .overlay header a .icon { + display: inline-block; + width: 20px; + height: 20px; + + background-position: 50% 50%; + background-size: 100%; + background-repeat: no-repeat; + } + .reveal > .overlay header a.close .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); + } + .reveal > .overlay header a.external .icon { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); + } + + .reveal > .overlay .viewport { + position: absolute; + display: flex; + top: $overlayHeaderHeight + $overlayHeaderPadding*2; + right: 0; + bottom: 0; + left: 0; + } + + .reveal > .overlay.overlay-preview .viewport iframe { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + border: 0; + + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + } + + .reveal > .overlay.overlay-preview.loaded .viewport iframe { + opacity: 1; + visibility: visible; + } + + .reveal > .overlay.overlay-preview.loaded .viewport-inner { + position: absolute; + z-index: -1; + left: 0; + top: 45%; + width: 100%; + text-align: center; + letter-spacing: normal; + } + .reveal > .overlay.overlay-preview .x-frame-error { + opacity: 0; + transition: opacity 0.3s ease 0.3s; + } + .reveal > .overlay.overlay-preview.loaded .x-frame-error { + opacity: 1; + } + + .reveal > .overlay.overlay-preview.loaded .spinner { + opacity: 0; + visibility: hidden; + transform: scale(0.2); + } + + .reveal > .overlay.overlay-help .viewport { + overflow: auto; + color: #fff; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner { + width: 600px; + margin: auto; + padding: 20px 20px 80px 20px; + text-align: center; + letter-spacing: normal; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner .title { + font-size: 20px; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table { + border: 1px solid #fff; + border-collapse: collapse; + font-size: 16px; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table th, + .reveal > .overlay.overlay-help .viewport .viewport-inner table td { + width: 200px; + padding: 14px; + border: 1px solid #fff; + vertical-align: middle; + } + + .reveal > .overlay.overlay-help .viewport .viewport-inner table th { + padding-top: 20px; + padding-bottom: 20px; + } + +/********************************************* + * PLAYBACK COMPONENT + *********************************************/ + +.reveal .playback { + position: absolute; + left: 15px; + bottom: 20px; + z-index: 30; + cursor: pointer; + transition: all 400ms ease; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); +} + +.reveal.overview .playback { + opacity: 0; + visibility: hidden; +} + + +/********************************************* + * CODE HIGHLGIHTING + *********************************************/ + +.reveal .hljs { + min-height: 100%; +} + +.reveal .hljs table { + margin: initial; +} + +.reveal .hljs-ln-code, +.reveal .hljs-ln-numbers { + padding: 0; + border: 0; +} + +.reveal .hljs-ln-numbers { + opacity: 0.6; + padding-right: 0.75em; + text-align: right; + vertical-align: top; +} + +.reveal .hljs.has-highlights tr:not(.highlight-line) { + opacity: 0.4; +} + +.reveal .hljs.has-highlights.fragment { + transition: all .2s ease; +} + +.reveal .hljs:not(:first-child).fragment { + position: absolute; + top: 0; + left: 0; + width: 100%; + box-sizing: border-box; +} + +.reveal pre[data-auto-animate-target] { + overflow: hidden; +} +.reveal pre[data-auto-animate-target] code { + height: 100%; +} + + +/********************************************* + * ROLLING LINKS + *********************************************/ + +.reveal .roll { + display: inline-block; + line-height: 1.2; + overflow: hidden; + + vertical-align: top; + perspective: 400px; + perspective-origin: 50% 50%; +} + .reveal .roll:hover { + background: none; + text-shadow: none; + } +.reveal .roll span { + display: block; + position: relative; + padding: 0 2px; + + pointer-events: none; + transition: all 400ms ease; + transform-origin: 50% 0%; + transform-style: preserve-3d; + backface-visibility: hidden; +} + .reveal .roll:hover span { + background: rgba(0,0,0,0.5); + transform: translate3d( 0px, 0px, -45px ) rotateX( 90deg ); + } +.reveal .roll span:after { + content: attr(data-title); + + display: block; + position: absolute; + left: 0; + top: 0; + padding: 0 2px; + backface-visibility: hidden; + transform-origin: 50% 0%; + transform: translate3d( 0px, 110%, 0px ) rotateX( -90deg ); +} + + +/********************************************* + * SPEAKER NOTES + *********************************************/ + +$notesWidthPercent: 25%; + +// Hide on-page notes +.reveal aside.notes { + display: none; +} + +// An interface element that can optionally be used to show the +// speaker notes to all viewers, on top of the presentation +.reveal .speaker-notes { + display: none; + position: absolute; + width: math.div($notesWidthPercent, (1 - math.div($notesWidthPercent,100))) * 1%; + height: 100%; + top: 0; + left: 100%; + padding: 14px 18px 14px 18px; + z-index: 1; + font-size: 18px; + line-height: 1.4; + border: 1px solid rgba( 0, 0, 0, 0.05 ); + color: #222; + background-color: #f5f5f5; + overflow: auto; + box-sizing: border-box; + text-align: left; + font-family: Helvetica, sans-serif; + -webkit-overflow-scrolling: touch; + + .notes-placeholder { + color: #ccc; + font-style: italic; + } + + &:focus { + outline: none; + } + + &:before { + content: 'Speaker notes'; + display: block; + margin-bottom: 10px; + opacity: 0.5; + } +} + + +.reveal.show-notes { + max-width: 100% - $notesWidthPercent; + overflow: visible; +} + +.reveal.show-notes .speaker-notes { + display: block; +} + +@media screen and (min-width: 1600px) { + .reveal .speaker-notes { + font-size: 20px; + } +} + +@media screen and (max-width: 1024px) { + .reveal.show-notes { + border-left: 0; + max-width: none; + max-height: 70%; + max-height: 70vh; + overflow: visible; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + left: 0; + width: 100%; + height: 30vh; + border: 0; + } +} + +@media screen and (max-width: 600px) { + .reveal.show-notes { + max-height: 60%; + max-height: 60vh; + } + + .reveal.show-notes .speaker-notes { + top: 100%; + height: 40vh; + } + + .reveal .speaker-notes { + font-size: 14px; + } +} + + +/********************************************* + * JUMP-TO-SLIDE COMPONENT + *********************************************/ + + .reveal .jump-to-slide { + position: absolute; + top: 15px; + left: 15px; + z-index: 30; + font-size: 32px; + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); +} + +.reveal .jump-to-slide-input { + background: transparent; + padding: 8px; + font-size: inherit; + color: currentColor; + border: 0; +} +.reveal .jump-to-slide-input::placeholder { + color: currentColor; + opacity: 0.5; +} + +.reveal.has-dark-background .jump-to-slide-input { + color: #fff; +} +.reveal.has-light-background .jump-to-slide-input { + color: #222; +} + +.reveal .jump-to-slide-input:focus { + outline: none; +} + + +/********************************************* + * ZOOM PLUGIN + *********************************************/ + +.zoomed .reveal *, +.zoomed .reveal *:before, +.zoomed .reveal *:after { + backface-visibility: visible !important; +} + +.zoomed .reveal .progress, +.zoomed .reveal .controls { + opacity: 0; +} + +.zoomed .reveal .roll span { + background: none; +} + +.zoomed .reveal .roll span:after { + visibility: hidden; +} + + +/********************************************* + * SCROLL VIEW + *********************************************/ +.reveal-viewport.loading-scroll-mode { + visibility: hidden; +} + +.reveal-viewport.reveal-scroll { + & { + margin: 0 auto; + overflow: auto; + overflow-x: hidden; + overflow-y: auto; + z-index: 1; + + --r-scrollbar-width: 7px; + --r-scrollbar-trigger-size: 5px; + --r-controls-spacing: 8px; + } + + @media screen and (max-width: 500px) { + --r-scrollbar-width: 3px; + --r-scrollbar-trigger-size: 3px; + } + + .controls, + .progress, + .playback, + .backgrounds, + .slide-number, + .speaker-notes { + display: none !important; + } + + .overlay, + .pause-overlay { + position: fixed; + } + + .reveal { + overflow: visible; + touch-action: manipulation; + } + + .slides { + position: static; + pointer-events: initial; + + left: auto; + top: auto; + width: 100% !important; + margin: 0; + padding: 0; + + overflow: visible; + display: block; + + perspective: none; + perspective-origin: 50% 50%; + } + + .scroll-page { + position: relative; + width: 100%; + height: calc(var(--page-height) + var(--page-scroll-padding)); + z-index: 1; + overflow: visible; + } + + .scroll-page-sticky { + position: sticky; + height: var(--page-height); + top: 0px; + } + + .scroll-page-content { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + } + + .scroll-page section { + visibility: visible !important; + display: block !important; + position: absolute !important; + width: var(--slide-width) !important; + height: var(--slide-height) !important; + top: 50% !important; + left: 50% !important; + opacity: 1 !important; + transform: scale(var(--slide-scale)) translate(-50%, -50%) !important; + transform-style: flat !important; + transform-origin: 0 0 !important; + } + + .slide-background { + display: block !important; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: auto !important; + visibility: visible; + opacity: 1; + touch-action: manipulation; + } +} + +// Chromium +.reveal-viewport.reveal-scroll[data-scrollbar="true"]::-webkit-scrollbar, +.reveal-viewport.reveal-scroll[data-scrollbar="auto"]::-webkit-scrollbar { + display: none; +} + +// Firefox +.reveal-viewport.reveal-scroll[data-scrollbar="true"], +.reveal-viewport.reveal-scroll[data-scrollbar="auto"] { + scrollbar-width: none; +} + +.reveal.has-dark-background, +.reveal-viewport.has-dark-background { + --r-overlay-element-bg-color: 240, 240, 240; + --r-overlay-element-fg-color: 0, 0, 0; +} +.reveal.has-light-background, +.reveal-viewport.has-light-background { + --r-overlay-element-bg-color: 0, 0, 0; + --r-overlay-element-fg-color: 240, 240, 240; +} + +.reveal-viewport.reveal-scroll .scrollbar { + position: sticky; + top: 50%; + z-index: 20; + opacity: 0; + transition: all 0.3s ease; + + &.visible, + &:hover { + opacity: 1; + } + + .scrollbar-inner { + position: absolute; + width: var(--r-scrollbar-width); + height: calc(var(--viewport-height) - var(--r-controls-spacing) * 2); + right: var(--r-controls-spacing); + top: 0; + transform: translateY(-50%); + border-radius: var(--r-scrollbar-width); + z-index: 10; + } + + .scrollbar-playhead { + position: absolute; + width: var(--r-scrollbar-width); + height: var(--r-scrollbar-width); + top: 0; + left: 0; + border-radius: var(--r-scrollbar-width); + background-color: rgba(var(--r-overlay-element-bg-color), 1); + z-index: 11; + transition: background-color 0.2s ease; + } + + .scrollbar-slide { + position: absolute; + width: 100%; + background-color: rgba(var(--r-overlay-element-bg-color), 0.2); + box-shadow: 0 0 0px 1px rgba(var(--r-overlay-element-fg-color), 0.1); + border-radius: var(--r-scrollbar-width); + transition: background-color 0.2s ease; + } + + // Hit area + .scrollbar-slide:after { + content: ''; + position: absolute; + width: 200%; + height: 100%; + top: 0; + left: -50%; + background: rgba( 0, 0, 0, 0 ); + z-index: -1; + } + + .scrollbar-slide:hover, + .scrollbar-slide.active { + background-color: rgba(var(--r-overlay-element-bg-color), 0.4); + } + + .scrollbar-trigger { + position: absolute; + width: 100%; + transition: background-color 0.2s ease; + } + + .scrollbar-slide.active.has-triggers { + background-color: rgba(var(--r-overlay-element-bg-color), 0.4); + z-index: 10; + } + + .scrollbar-slide.active .scrollbar-trigger:after { + content: ''; + position: absolute; + width: var(--r-scrollbar-trigger-size); + height: var(--r-scrollbar-trigger-size); + border-radius: 20px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: rgba(var(--r-overlay-element-bg-color), 1); + transition: transform 0.2s ease, opacity 0.2s ease; + opacity: 0.4; + } + + .scrollbar-slide.active .scrollbar-trigger.active:after, + .scrollbar-slide.active .scrollbar-trigger.active ~ .scrollbar-trigger:after { + opacity: 1; + } + + .scrollbar-slide.active .scrollbar-trigger ~ .scrollbar-trigger.active:after { + transform: translate(calc( var(--r-scrollbar-width) * -2), 0); + background-color: rgba(var(--r-overlay-element-bg-color), 1); + } +} + + +/********************************************* + * PRINT STYLES + *********************************************/ + +@import 'print/pdf.scss'; +@import 'print/paper.scss'; + diff --git a/src/public/bash/css/theme/README.md b/src/public/bash/css/theme/README.md new file mode 100644 index 0000000..30916c4 --- /dev/null +++ b/src/public/bash/css/theme/README.md @@ -0,0 +1,21 @@ +## Dependencies + +Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment installed before proceeding: https://revealjs.com/installation/#full-setup + +## Creating a Theme + +To create your own theme, start by duplicating a ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source). It will be automatically compiled from Sass to CSS (see the [gulpfile](https://github.com/hakimel/reveal.js/blob/master/gulpfile.js)) when you run `npm run build -- css-themes`. + +Each theme file does four things in the following order: + +1. **Include [/css/theme/template/mixins.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/mixins.scss)** +Shared utility functions. + +2. **Include [/css/theme/template/settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss)** +Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3. + +3. **Override** +This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding any selectors and styles you please. + +4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)** +The template theme file which will generate final CSS output based on the currently defined variables. diff --git a/src/public/bash/css/theme/source/beige.scss b/src/public/bash/css/theme/source/beige.scss new file mode 100644 index 0000000..7598b94 --- /dev/null +++ b/src/public/bash/css/theme/source/beige.scss @@ -0,0 +1,44 @@ +/** + * Beige theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(./fonts/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$mainColor: #333; +$headingColor: #333; +$headingTextShadow: none; +$backgroundColor: #f7f3de; +$linkColor: #8b743d; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: rgba(79, 64, 28, 0.99); +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) ); +} + +// Change text colors against dark slide backgrounds +@include dark-bg-text-color(#fff); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/black-contrast.scss b/src/public/bash/css/theme/source/black-contrast.scss new file mode 100644 index 0000000..9e1a2ca --- /dev/null +++ b/src/public/bash/css/theme/source/black-contrast.scss @@ -0,0 +1,49 @@ +/** + * Black compact & high contrast reveal.js theme, with headers not in capitals. + * + * By Peter Kehl. Based on black.(s)css by Hakim El Hattab, http://hakim.se + * + * - Keep the source similar to black.css - for easy comparison. + * - $mainFontSize controls code blocks, too (although under some ratio). + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(./fonts/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #000000; + +$mainColor: #fff; +$headingColor: #fff; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #42affa; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +// Change text colors against light slide backgrounds +@include light-bg-text-color(#000); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/black.scss b/src/public/bash/css/theme/source/black.scss new file mode 100644 index 0000000..7c655c4 --- /dev/null +++ b/src/public/bash/css/theme/source/black.scss @@ -0,0 +1,46 @@ +/** + * Black theme for reveal.js. This is the opposite of the 'white' theme. + * + * By Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(./fonts/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #191919; + +$mainColor: #fff; +$headingColor: #fff; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #42affa; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: rgba( $linkColor, 0.75 ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +// Change text colors against light slide backgrounds +@include light-bg-text-color(#222); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/blood.scss b/src/public/bash/css/theme/source/blood.scss new file mode 100644 index 0000000..b5a8679 --- /dev/null +++ b/src/public/bash/css/theme/source/blood.scss @@ -0,0 +1,87 @@ +/** + * Blood theme for reveal.js + * Author: Walther http://github.com/Walther + * + * Designed to be used with highlight.js theme + * "monokai_sublime.css" available from + * https://github.com/isagalaev/highlight.js/ + * + * For other themes, change $codeBackground accordingly. + * + */ + + // Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + +// Include theme-specific fonts + +@import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); + +// Colors used in the theme +$blood: #a23; +$coal: #222; +$codeBackground: #23241f; + +$backgroundColor: $coal; + +// Main text +$mainFont: Ubuntu, 'sans-serif'; +$mainColor: #eee; + +// Headings +$headingFont: Ubuntu, 'sans-serif'; +$headingTextShadow: 2px 2px 2px $coal; + +// h1 shadow, borrowed humbly from +// (c) Default theme by Hakim El Hattab +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Links +$linkColor: $blood; +$linkColorHover: lighten( $linkColor, 20% ); + +// Text selection +$selectionBackgroundColor: $blood; +$selectionColor: #fff; + +// Change text colors against dark slide backgrounds +@include light-bg-text-color(#222); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- + +// some overrides after theme template import + +.reveal p { + font-weight: 300; + text-shadow: 1px 1px $coal; +} + +section.has-light-background { + p, h1, h2, h3, h4 { + text-shadow: none; + } +} + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + font-weight: 700; +} + +.reveal p code { + background-color: $codeBackground; + display: inline-block; + border-radius: 7px; +} + +.reveal small code { + vertical-align: baseline; +} \ No newline at end of file diff --git a/src/public/bash/css/theme/source/dracula.scss b/src/public/bash/css/theme/source/dracula.scss new file mode 100644 index 0000000..ae968b8 --- /dev/null +++ b/src/public/bash/css/theme/source/dracula.scss @@ -0,0 +1,106 @@ +/** + * Dracula Dark theme for reveal.js. + * Based on https://draculatheme.com + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +$systemFontsSansSerif: -apple-system, + BlinkMacSystemFont, + avenir next, + avenir, + segoe ui, + helvetica neue, + helvetica, + Cantarell, + Ubuntu, + roboto, + noto, + arial, + sans-serif; +$systemFontsMono: Menlo, + Consolas, + Monaco, + Liberation Mono, + Lucida Console, + monospace; + +/** + * Dracula colors by Zeno Rocha + * https://draculatheme.com/contribute + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +$background: #282A36; +$foreground: #F8F8F2; +$selection: #44475A; +$comment: #6272A4; +$red: #FF5555; +$orange: #FFB86C; +$yellow: #F1FA8C; +$green: #50FA7B; +$purple: #BD93F9; +$cyan: #8BE9FD; +$pink: #FF79C6; + + + +// Override theme settings (see ../template/settings.scss) +$mainColor: $foreground; +$headingColor: $purple; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: $background; +$linkColor: $pink; +$linkColorHover: $cyan; +$selectionBackgroundColor: $selection; +$inlineCodeColor: $green; +$listBulletColor: $cyan; + +$mainFont: $systemFontsSansSerif; +$codeFont: "Fira Code", $systemFontsMono; + +// Change text colors against light slide backgrounds +@include light-bg-text-color($background); + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- + +// Define additional color effects based on Dracula spec +// https://spec.draculatheme.com/ +:root { + --r-bold-color: #{$orange}; + --r-italic-color: #{$yellow}; + --r-inline-code-color: #{$inlineCodeColor}; + --r-list-bullet-color: #{$listBulletColor}; +} + +.reveal { + strong, b { + color: var(--r-bold-color); + } + em, i, blockquote { + color: var(--r-italic-color); + } + code { + color: var(--r-inline-code-color); + } + // Dracula colored list bullets and numbers + ul, ol { + li::marker { + color: var(--r-list-bullet-color); + } + } +} + diff --git a/src/public/bash/css/theme/source/league.scss b/src/public/bash/css/theme/source/league.scss new file mode 100644 index 0000000..ee01258 --- /dev/null +++ b/src/public/bash/css/theme/source/league.scss @@ -0,0 +1,36 @@ +/** + * League theme for reveal.js. + * + * This was the default theme pre-3.0.0. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(./fonts/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + +// Override theme settings (see ../template/settings.scss) +$headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2); +$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15); + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( rgba(28,30,32,1), rgba(85,90,95,1) ); +} + +// Change text colors against light slide backgrounds +@include light-bg-text-color(#222); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/moon.scss b/src/public/bash/css/theme/source/moon.scss new file mode 100644 index 0000000..59ef0a9 --- /dev/null +++ b/src/public/bash/css/theme/source/moon.scss @@ -0,0 +1,54 @@ +/** + * Solarized Dark theme for reveal.js. + * Author: Achim Staebler + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(./fonts/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + +/** + * Solarized colors by Ethan Schoonover + */ + +// Solarized colors +$base03: #002b36; +$base02: #073642; +$base01: #586e75; +$base00: #657b83; +$base0: #839496; +$base1: #93a1a1; +$base2: #eee8d5; +$base3: #fdf6e3; +$yellow: #b58900; +$orange: #cb4b16; +$red: #dc322f; +$magenta: #d33682; +$violet: #6c71c4; +$blue: #268bd2; +$cyan: #2aa198; +$green: #859900; + +// Override theme settings (see ../template/settings.scss) +$mainColor: $base1; +$headingColor: $base2; +$headingTextShadow: none; +$backgroundColor: $base03; +$linkColor: $blue; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: $magenta; + +// Change text colors against light slide backgrounds +@include light-bg-text-color(#222); + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/night.scss b/src/public/bash/css/theme/source/night.scss new file mode 100644 index 0000000..98a2062 --- /dev/null +++ b/src/public/bash/css/theme/source/night.scss @@ -0,0 +1,37 @@ +/** + * Black theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=Montserrat:700); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #111; + +$mainFont: 'Open Sans', sans-serif; +$linkColor: #e7ad52; +$linkColorHover: lighten( $linkColor, 20% ); +$headingFont: 'Montserrat', Impact, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: -0.03em; +$headingTextTransform: none; +$selectionBackgroundColor: #e7ad52; + +// Change text colors against light slide backgrounds +@include light-bg-text-color(#222); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/src/public/bash/css/theme/source/serif.scss b/src/public/bash/css/theme/source/serif.scss new file mode 100644 index 0000000..babec4d --- /dev/null +++ b/src/public/bash/css/theme/source/serif.scss @@ -0,0 +1,41 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is brown. + * + * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed. + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; +$mainColor: #000; +$headingFont: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif; +$headingColor: #383D3D; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: #F0F1EB; +$linkColor: #51483D; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: #26351C; + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +.reveal a { + line-height: 1.3em; +} + +// Change text colors against dark slide backgrounds +@include dark-bg-text-color(#fff); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/simple.scss b/src/public/bash/css/theme/source/simple.scss new file mode 100644 index 0000000..51a21af --- /dev/null +++ b/src/public/bash/css/theme/source/simple.scss @@ -0,0 +1,43 @@ +/** + * A simple theme for reveal.js presentations, similar + * to the default theme. The accent color is darkblue. + * + * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. + * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Lato', sans-serif; +$mainColor: #000; +$headingFont: 'News Cycle', Impact, sans-serif; +$headingColor: #000; +$headingTextShadow: none; +$headingTextTransform: none; +$backgroundColor: #fff; +$linkColor: #00008B; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: rgba(0, 0, 0, 0.99); + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +// Change text colors against dark slide backgrounds +@include dark-bg-text-color(#fff); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- \ No newline at end of file diff --git a/src/public/bash/css/theme/source/sky.scss b/src/public/bash/css/theme/source/sky.scss new file mode 100644 index 0000000..457e9e5 --- /dev/null +++ b/src/public/bash/css/theme/source/sky.scss @@ -0,0 +1,52 @@ +/** + * Sky theme for reveal.js. + * + * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); +@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); + + +// Override theme settings (see ../template/settings.scss) +$mainFont: 'Open Sans', sans-serif; +$mainColor: #333; +$headingFont: 'Quicksand', sans-serif; +$headingColor: #333; +$headingLetterSpacing: -0.08em; +$headingTextShadow: none; +$backgroundColor: #f7fbfc; +$linkColor: #3b759e; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: #134674; + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +// Fix links so they are not cut off +.reveal a { + line-height: 1.3em; +} + +// Background generator +@mixin bodyBackground() { + @include radial-gradient( #add9e4, #f7fbfc ); +} + +// Change text colors against dark slide backgrounds +@include dark-bg-text-color(#fff); + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/solarized.scss b/src/public/bash/css/theme/source/solarized.scss new file mode 100644 index 0000000..f325345 --- /dev/null +++ b/src/public/bash/css/theme/source/solarized.scss @@ -0,0 +1,66 @@ +/** + * Solarized Light theme for reveal.js. + * Author: Achim Staebler + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + + +// Include theme-specific fonts +@import url(./fonts/league-gothic/league-gothic.css); +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); + + +/** + * Solarized colors by Ethan Schoonover + */ +html * { + color-profile: sRGB; + rendering-intent: auto; +} + +// Solarized colors +$base03: #002b36; +$base02: #073642; +$base01: #586e75; +$base00: #657b83; +$base0: #839496; +$base1: #93a1a1; +$base2: #eee8d5; +$base3: #fdf6e3; +$yellow: #b58900; +$orange: #cb4b16; +$red: #dc322f; +$magenta: #d33682; +$violet: #6c71c4; +$blue: #268bd2; +$cyan: #2aa198; +$green: #859900; + +// Override theme settings (see ../template/settings.scss) +$mainColor: $base00; +$headingColor: $base01; +$headingTextShadow: none; +$backgroundColor: $base3; +$linkColor: $blue; +$linkColorHover: lighten( $linkColor, 20% ); +$selectionBackgroundColor: $magenta; + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +// Background generator +// @mixin bodyBackground() { +// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) ); +// } + + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/white-contrast.scss b/src/public/bash/css/theme/source/white-contrast.scss new file mode 100644 index 0000000..e22007e --- /dev/null +++ b/src/public/bash/css/theme/source/white-contrast.scss @@ -0,0 +1,52 @@ +/** + * White compact & high contrast reveal.js theme, with headers not in capitals. + * + * By Peter Kehl. Based on white.(s)css by Hakim El Hattab, http://hakim.se + * + * - Keep the source similar to black.css - for easy comparison. + * - $mainFontSize controls code blocks, too (although under some ratio). + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(./fonts/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #fff; + +$mainColor: #000; +$headingColor: #000; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #2a76dd; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +// Change text colors against dark slide backgrounds +@include dark-bg-text-color(#fff); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/source/white.scss b/src/public/bash/css/theme/source/white.scss new file mode 100644 index 0000000..a2b1292 --- /dev/null +++ b/src/public/bash/css/theme/source/white.scss @@ -0,0 +1,49 @@ +/** + * White theme for reveal.js. This is the opposite of the 'black' theme. + * + * By Hakim El Hattab, http://hakim.se + */ + + +// Default mixins and settings ----------------- +@import "../template/mixins"; +@import "../template/settings"; +// --------------------------------------------- + + +// Include theme-specific fonts +@import url(./fonts/source-sans-pro/source-sans-pro.css); + + +// Override theme settings (see ../template/settings.scss) +$backgroundColor: #fff; + +$mainColor: #222; +$headingColor: #222; + +$mainFontSize: 42px; +$mainFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingFont: 'Source Sans Pro', Helvetica, sans-serif; +$headingTextShadow: none; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingFontWeight: 600; +$linkColor: #2a76dd; +$linkColorHover: lighten( $linkColor, 15% ); +$selectionBackgroundColor: lighten( $linkColor, 25% ); + +$heading1Size: 2.5em; +$heading2Size: 1.6em; +$heading3Size: 1.3em; +$heading4Size: 1.0em; + +$overlayElementBgColor: 0, 0, 0; +$overlayElementFgColor: 240, 240, 240; + +// Change text colors against dark slide backgrounds +@include dark-bg-text-color(#fff); + + +// Theme template ------------------------------ +@import "../template/theme"; +// --------------------------------------------- diff --git a/src/public/bash/css/theme/template/exposer.scss b/src/public/bash/css/theme/template/exposer.scss new file mode 100644 index 0000000..2e9288d --- /dev/null +++ b/src/public/bash/css/theme/template/exposer.scss @@ -0,0 +1,30 @@ +// Exposes theme's variables for easy re-use in CSS for plugin authors + +:root { + --r-background-color: #{$backgroundColor}; + --r-main-font: #{$mainFont}; + --r-main-font-size: #{$mainFontSize}; + --r-main-color: #{$mainColor}; + --r-block-margin: #{$blockMargin}; + --r-heading-margin: #{$headingMargin}; + --r-heading-font: #{$headingFont}; + --r-heading-color: #{$headingColor}; + --r-heading-line-height: #{$headingLineHeight}; + --r-heading-letter-spacing: #{$headingLetterSpacing}; + --r-heading-text-transform: #{$headingTextTransform}; + --r-heading-text-shadow: #{$headingTextShadow}; + --r-heading-font-weight: #{$headingFontWeight}; + --r-heading1-text-shadow: #{$heading1TextShadow}; + --r-heading1-size: #{$heading1Size}; + --r-heading2-size: #{$heading2Size}; + --r-heading3-size: #{$heading3Size}; + --r-heading4-size: #{$heading4Size}; + --r-code-font: #{$codeFont}; + --r-link-color: #{$linkColor}; + --r-link-color-dark: #{darken($linkColor , 15% )}; + --r-link-color-hover: #{$linkColorHover}; + --r-selection-background-color: #{$selectionBackgroundColor}; + --r-selection-color: #{$selectionColor}; + --r-overlay-element-bg-color: #{$overlayElementBgColor}; + --r-overlay-element-fg-color: #{$overlayElementFgColor}; +} diff --git a/src/public/bash/css/theme/template/mixins.scss b/src/public/bash/css/theme/template/mixins.scss new file mode 100644 index 0000000..17a3db5 --- /dev/null +++ b/src/public/bash/css/theme/template/mixins.scss @@ -0,0 +1,45 @@ +@mixin vertical-gradient( $top, $bottom ) { + background: $top; + background: -moz-linear-gradient( top, $top 0%, $bottom 100% ); + background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) ); + background: -webkit-linear-gradient( top, $top 0%, $bottom 100% ); + background: -o-linear-gradient( top, $top 0%, $bottom 100% ); + background: -ms-linear-gradient( top, $top 0%, $bottom 100% ); + background: linear-gradient( top, $top 0%, $bottom 100% ); +} + +@mixin horizontal-gradient( $top, $bottom ) { + background: $top; + background: -moz-linear-gradient( left, $top 0%, $bottom 100% ); + background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) ); + background: -webkit-linear-gradient( left, $top 0%, $bottom 100% ); + background: -o-linear-gradient( left, $top 0%, $bottom 100% ); + background: -ms-linear-gradient( left, $top 0%, $bottom 100% ); + background: linear-gradient( left, $top 0%, $bottom 100% ); +} + +@mixin radial-gradient( $outer, $inner, $type: circle ) { + background: $outer; + background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) ); + background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); + background: radial-gradient( center, $type cover, $inner 0%, $outer 100% ); +} + +@mixin light-bg-text-color( $color ) { + section.has-light-background { + &, h1, h2, h3, h4, h5, h6 { + color: $color; + } + } +} + +@mixin dark-bg-text-color( $color ) { + section.has-dark-background { + &, h1, h2, h3, h4, h5, h6 { + color: $color; + } + } +} \ No newline at end of file diff --git a/src/public/bash/css/theme/template/settings.scss b/src/public/bash/css/theme/template/settings.scss new file mode 100644 index 0000000..3d54ac8 --- /dev/null +++ b/src/public/bash/css/theme/template/settings.scss @@ -0,0 +1,50 @@ +// Base settings for all themes that can optionally be +// overridden by the super-theme + +// Background of the presentation +$backgroundColor: #2b2b2b; + +// Primary/body text +$mainFont: 'Lato', sans-serif; +$mainFontSize: 40px; +$mainColor: #eee; + +// Vertical spacing between blocks of text +$blockMargin: 20px; + +// Headings +$headingMargin: 0 0 $blockMargin 0; +$headingFont: 'League Gothic', Impact, sans-serif; +$headingColor: #eee; +$headingLineHeight: 1.2; +$headingLetterSpacing: normal; +$headingTextTransform: uppercase; +$headingTextShadow: none; +$headingFontWeight: normal; +$heading1TextShadow: $headingTextShadow; + +$heading1Size: 3.77em; +$heading2Size: 2.11em; +$heading3Size: 1.55em; +$heading4Size: 1.00em; + +$codeFont: monospace; + +// Links and actions +$linkColor: #13DAEC; +$linkColorHover: lighten( $linkColor, 20% ); + +// Text selection +$selectionBackgroundColor: #FF5E99; +$selectionColor: #fff; + +// Colors used for UI elements that are overlaid on top of +// the presentation +$overlayElementBgColor: 240, 240, 240; +$overlayElementFgColor: 0, 0, 0; + +// Generates the presentation background, can be overridden +// to return a background image or gradient +@mixin bodyBackground() { + background: $backgroundColor; +} diff --git a/src/public/bash/css/theme/template/theme.scss b/src/public/bash/css/theme/template/theme.scss new file mode 100644 index 0000000..bc377d3 --- /dev/null +++ b/src/public/bash/css/theme/template/theme.scss @@ -0,0 +1,331 @@ +// Base theme template for reveal.js + +/********************************************* + * GLOBAL STYLES + *********************************************/ + +@import "./exposer"; + +.reveal-viewport { + @include bodyBackground(); + background-color: var(--r-background-color); +} + +.reveal { + font-family: var(--r-main-font); + font-size: var(--r-main-font-size); + font-weight: normal; + color: var(--r-main-color); +} + +.reveal ::selection { + color: var(--r-selection-color); + background: var(--r-selection-background-color); + text-shadow: none; +} + +.reveal ::-moz-selection { + color: var(--r-selection-color); + background: var(--r-selection-background-color); + text-shadow: none; +} + +.reveal .slides section, +.reveal .slides section>section { + line-height: 1.3; + font-weight: inherit; +} + +/********************************************* + * HEADERS + *********************************************/ + +.reveal h1, +.reveal h2, +.reveal h3, +.reveal h4, +.reveal h5, +.reveal h6 { + margin: var(--r-heading-margin); + color: var(--r-heading-color); + + font-family: var(--r-heading-font); + font-weight: var(--r-heading-font-weight); + line-height: var(--r-heading-line-height); + letter-spacing: var(--r-heading-letter-spacing); + + text-transform: var(--r-heading-text-transform); + text-shadow: var(--r-heading-text-shadow); + + word-wrap: break-word; +} + +.reveal h1 {font-size: var(--r-heading1-size); } +.reveal h2 {font-size: var(--r-heading2-size); } +.reveal h3 {font-size: var(--r-heading3-size); } +.reveal h4 {font-size: var(--r-heading4-size); } + +.reveal h1 { + text-shadow: var(--r-heading1-text-shadow); +} + + +/********************************************* + * OTHER + *********************************************/ + +.reveal p { + margin: var(--r-block-margin) 0; + line-height: 1.3; +} + +/* Remove trailing margins after titles */ +.reveal h1:last-child, +.reveal h2:last-child, +.reveal h3:last-child, +.reveal h4:last-child, +.reveal h5:last-child, +.reveal h6:last-child { + margin-bottom: 0; +} + +/* Ensure certain elements are never larger than the slide itself */ +.reveal img, +.reveal video, +.reveal iframe { + max-width: 95%; + max-height: 95%; +} +.reveal strong, +.reveal b { + font-weight: bold; +} + +.reveal em { + font-style: italic; +} + +.reveal ol, +.reveal dl, +.reveal ul { + display: inline-block; + + text-align: left; + margin: 0 0 0 1em; +} + +.reveal ol { + list-style-type: decimal; +} + +.reveal ul { + list-style-type: disc; +} + +.reveal ul ul { + list-style-type: square; +} + +.reveal ul ul ul { + list-style-type: circle; +} + +.reveal ul ul, +.reveal ul ol, +.reveal ol ol, +.reveal ol ul { + display: block; + margin-left: 40px; +} + +.reveal dt { + font-weight: bold; +} + +.reveal dd { + margin-left: 40px; +} + +.reveal blockquote { + display: block; + position: relative; + width: 70%; + margin: var(--r-block-margin) auto; + padding: 5px; + + font-style: italic; + background: rgba(255, 255, 255, 0.05); + box-shadow: 0px 0px 2px rgba(0,0,0,0.2); +} + .reveal blockquote p:first-child, + .reveal blockquote p:last-child { + display: inline-block; + } + +.reveal q { + font-style: italic; +} + +.reveal pre { + display: block; + position: relative; + width: 90%; + margin: var(--r-block-margin) auto; + + text-align: left; + font-size: 0.55em; + font-family: var(--r-code-font); + line-height: 1.2em; + + word-wrap: break-word; + + box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); +} + +.reveal code { + font-family: var(--r-code-font); + text-transform: none; + tab-size: 2; +} + +.reveal pre code { + display: block; + padding: 5px; + overflow: auto; + max-height: 400px; + word-wrap: normal; +} + +.reveal .code-wrapper { + white-space: normal; +} + +.reveal .code-wrapper code { + white-space: pre; +} + +.reveal table { + margin: auto; + border-collapse: collapse; + border-spacing: 0; +} + +.reveal table th { + font-weight: bold; +} + +.reveal table th, +.reveal table td { + text-align: left; + padding: 0.2em 0.5em 0.2em 0.5em; + border-bottom: 1px solid; +} + +.reveal table th[align="center"], +.reveal table td[align="center"] { + text-align: center; +} + +.reveal table th[align="right"], +.reveal table td[align="right"] { + text-align: right; +} + +.reveal table tbody tr:last-child th, +.reveal table tbody tr:last-child td { + border-bottom: none; +} + +.reveal sup { + vertical-align: super; + font-size: smaller; +} +.reveal sub { + vertical-align: sub; + font-size: smaller; +} + +.reveal small { + display: inline-block; + font-size: 0.6em; + line-height: 1.2em; + vertical-align: top; +} + +.reveal small * { + vertical-align: top; +} + +.reveal img { + margin: var(--r-block-margin) 0; +} + + +/********************************************* + * LINKS + *********************************************/ + +.reveal a { + color: var(--r-link-color); + text-decoration: none; + transition: color .15s ease; +} + .reveal a:hover { + color: var(--r-link-color-hover); + text-shadow: none; + border: none; + } + +.reveal .roll span:after { + color: #fff; + // background: darken( var(--r-link-color), 15% ); + background: var(--r-link-color-dark); + +} + + +/********************************************* + * Frame helper + *********************************************/ + +.reveal .r-frame { + border: 4px solid var(--r-main-color); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); +} + +.reveal a .r-frame { + transition: all .15s linear; +} + +.reveal a:hover .r-frame { + border-color: var(--r-link-color); + box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); +} + + +/********************************************* + * NAVIGATION CONTROLS + *********************************************/ + +.reveal .controls { + color: var(--r-link-color); +} + + +/********************************************* + * PROGRESS BAR + *********************************************/ + +.reveal .progress { + background: rgba(0,0,0,0.2); + color: var(--r-link-color); +} + +/********************************************* + * PRINT BACKGROUND + *********************************************/ + @media print { + .backgrounds { + background-color: var(--r-background-color); + } +} diff --git a/src/public/bash/dist/reset.css b/src/public/bash/dist/reset.css new file mode 100644 index 0000000..e238539 --- /dev/null +++ b/src/public/bash/dist/reset.css @@ -0,0 +1,30 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v4.0 | 20180602 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +main, menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, main, menu, nav, section { + display: block; +} \ No newline at end of file diff --git a/src/public/bash/dist/reveal.css b/src/public/bash/dist/reveal.css new file mode 100644 index 0000000..072327d --- /dev/null +++ b/src/public/bash/dist/reveal.css @@ -0,0 +1,8 @@ +/*! +* reveal.js 5.0.5 +* https://revealjs.com +* MIT licensed +* +* Copyright (C) 2011-2024 Hakim El Hattab, https://hakim.se +*/ +.reveal .r-stretch,.reveal .stretch{max-width:none;max-height:none}.reveal pre.r-stretch code,.reveal pre.stretch code{height:100%;max-height:100%;box-sizing:border-box}.reveal .r-fit-text{display:inline-block;white-space:nowrap}.reveal .r-stack{display:grid}.reveal .r-stack>*{grid-area:1/1;margin:auto}.reveal .r-hstack,.reveal .r-vstack{display:flex}.reveal .r-hstack img,.reveal .r-hstack video,.reveal .r-vstack img,.reveal .r-vstack video{min-width:0;min-height:0;object-fit:contain}.reveal .r-vstack{flex-direction:column;align-items:center;justify-content:center}.reveal .r-hstack{flex-direction:row;align-items:center;justify-content:center}.reveal .items-stretch{align-items:stretch}.reveal .items-start{align-items:flex-start}.reveal .items-center{align-items:center}.reveal .items-end{align-items:flex-end}.reveal .justify-between{justify-content:space-between}.reveal .justify-around{justify-content:space-around}.reveal .justify-start{justify-content:flex-start}.reveal .justify-center{justify-content:center}.reveal .justify-end{justify-content:flex-end}html.reveal-full-page{width:100%;height:100%;height:100vh;height:calc(var(--vh,1vh) * 100);height:100svh;overflow:hidden}.reveal-viewport{height:100%;overflow:hidden;position:relative;line-height:1;margin:0;background-color:#fff;color:#000;--r-controls-spacing:12px}.reveal-viewport:fullscreen{top:0!important;left:0!important;width:100%!important;height:100%!important;transform:none!important}.reveal .fragment{transition:all .2s ease}.reveal .fragment:not(.custom){opacity:0;visibility:hidden;will-change:opacity}.reveal .fragment.visible{opacity:1;visibility:inherit}.reveal .fragment.disabled{transition:none}.reveal .fragment.grow{opacity:1;visibility:inherit}.reveal .fragment.grow.visible{transform:scale(1.3)}.reveal .fragment.shrink{opacity:1;visibility:inherit}.reveal .fragment.shrink.visible{transform:scale(.7)}.reveal .fragment.zoom-in{transform:scale(.1)}.reveal .fragment.zoom-in.visible{transform:none}.reveal .fragment.fade-out{opacity:1;visibility:inherit}.reveal .fragment.fade-out.visible{opacity:0;visibility:hidden}.reveal .fragment.semi-fade-out{opacity:1;visibility:inherit}.reveal .fragment.semi-fade-out.visible{opacity:.5;visibility:inherit}.reveal .fragment.strike{opacity:1;visibility:inherit}.reveal .fragment.strike.visible{text-decoration:line-through}.reveal .fragment.fade-up{transform:translate(0,40px)}.reveal .fragment.fade-up.visible{transform:translate(0,0)}.reveal .fragment.fade-down{transform:translate(0,-40px)}.reveal .fragment.fade-down.visible{transform:translate(0,0)}.reveal .fragment.fade-right{transform:translate(-40px,0)}.reveal .fragment.fade-right.visible{transform:translate(0,0)}.reveal .fragment.fade-left{transform:translate(40px,0)}.reveal .fragment.fade-left.visible{transform:translate(0,0)}.reveal .fragment.current-visible,.reveal .fragment.fade-in-then-out{opacity:0;visibility:hidden}.reveal .fragment.current-visible.current-fragment,.reveal .fragment.fade-in-then-out.current-fragment{opacity:1;visibility:inherit}.reveal .fragment.fade-in-then-semi-out{opacity:0;visibility:hidden}.reveal .fragment.fade-in-then-semi-out.visible{opacity:.5;visibility:inherit}.reveal .fragment.fade-in-then-semi-out.current-fragment{opacity:1;visibility:inherit}.reveal .fragment.highlight-blue,.reveal .fragment.highlight-current-blue,.reveal .fragment.highlight-current-green,.reveal .fragment.highlight-current-red,.reveal .fragment.highlight-green,.reveal .fragment.highlight-red{opacity:1;visibility:inherit}.reveal .fragment.highlight-red.visible{color:#ff2c2d}.reveal .fragment.highlight-green.visible{color:#17ff2e}.reveal .fragment.highlight-blue.visible{color:#1b91ff}.reveal .fragment.highlight-current-red.current-fragment{color:#ff2c2d}.reveal .fragment.highlight-current-green.current-fragment{color:#17ff2e}.reveal .fragment.highlight-current-blue.current-fragment{color:#1b91ff}.reveal:after{content:"";font-style:italic}.reveal iframe{z-index:1}.reveal a{position:relative}@keyframes bounce-right{0%,10%,25%,40%,50%{transform:translateX(0)}20%{transform:translateX(10px)}30%{transform:translateX(-5px)}}@keyframes bounce-left{0%,10%,25%,40%,50%{transform:translateX(0)}20%{transform:translateX(-10px)}30%{transform:translateX(5px)}}@keyframes bounce-down{0%,10%,25%,40%,50%{transform:translateY(0)}20%{transform:translateY(10px)}30%{transform:translateY(-5px)}}.reveal .controls{display:none;position:absolute;top:auto;bottom:var(--r-controls-spacing);right:var(--r-controls-spacing);left:auto;z-index:11;color:#000;pointer-events:none;font-size:10px}.reveal .controls button{position:absolute;padding:0;background-color:transparent;border:0;outline:0;cursor:pointer;color:currentColor;transform:scale(.9999);transition:color .2s ease,opacity .2s ease,transform .2s ease;z-index:2;pointer-events:auto;font-size:inherit;visibility:hidden;opacity:0;-webkit-appearance:none;-webkit-tap-highlight-color:transparent}.reveal .controls .controls-arrow:after,.reveal .controls .controls-arrow:before{content:"";position:absolute;top:0;left:0;width:2.6em;height:.5em;border-radius:.25em;background-color:currentColor;transition:all .15s ease,background-color .8s ease;transform-origin:.2em 50%;will-change:transform}.reveal .controls .controls-arrow{position:relative;width:3.6em;height:3.6em}.reveal .controls .controls-arrow:before{transform:translateX(.5em) translateY(1.55em) rotate(45deg)}.reveal .controls .controls-arrow:after{transform:translateX(.5em) translateY(1.55em) rotate(-45deg)}.reveal .controls .controls-arrow:hover:before{transform:translateX(.5em) translateY(1.55em) rotate(40deg)}.reveal .controls .controls-arrow:hover:after{transform:translateX(.5em) translateY(1.55em) rotate(-40deg)}.reveal .controls .controls-arrow:active:before{transform:translateX(.5em) translateY(1.55em) rotate(36deg)}.reveal .controls .controls-arrow:active:after{transform:translateX(.5em) translateY(1.55em) rotate(-36deg)}.reveal .controls .navigate-left{right:6.4em;bottom:3.2em;transform:translateX(-10px)}.reveal .controls .navigate-left.highlight{animation:bounce-left 2s 50 both ease-out}.reveal .controls .navigate-right{right:0;bottom:3.2em;transform:translateX(10px)}.reveal .controls .navigate-right .controls-arrow{transform:rotate(180deg)}.reveal .controls .navigate-right.highlight{animation:bounce-right 2s 50 both ease-out}.reveal .controls .navigate-up{right:3.2em;bottom:6.4em;transform:translateY(-10px)}.reveal .controls .navigate-up .controls-arrow{transform:rotate(90deg)}.reveal .controls .navigate-down{right:3.2em;bottom:-1.4em;padding-bottom:1.4em;transform:translateY(10px)}.reveal .controls .navigate-down .controls-arrow{transform:rotate(-90deg)}.reveal .controls .navigate-down.highlight{animation:bounce-down 2s 50 both ease-out}.reveal .controls[data-controls-back-arrows=faded] .navigate-up.enabled{opacity:.3}.reveal .controls[data-controls-back-arrows=faded] .navigate-up.enabled:hover{opacity:1}.reveal .controls[data-controls-back-arrows=hidden] .navigate-up.enabled{opacity:0;visibility:hidden}.reveal .controls .enabled{visibility:visible;opacity:.9;cursor:pointer;transform:none}.reveal .controls .enabled.fragmented{opacity:.5}.reveal .controls .enabled.fragmented:hover,.reveal .controls .enabled:hover{opacity:1}.reveal:not(.rtl) .controls[data-controls-back-arrows=faded] .navigate-left.enabled{opacity:.3}.reveal:not(.rtl) .controls[data-controls-back-arrows=faded] .navigate-left.enabled:hover{opacity:1}.reveal:not(.rtl) .controls[data-controls-back-arrows=hidden] .navigate-left.enabled{opacity:0;visibility:hidden}.reveal.rtl .controls[data-controls-back-arrows=faded] .navigate-right.enabled{opacity:.3}.reveal.rtl .controls[data-controls-back-arrows=faded] .navigate-right.enabled:hover{opacity:1}.reveal.rtl .controls[data-controls-back-arrows=hidden] .navigate-right.enabled{opacity:0;visibility:hidden}.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-down,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-up{display:none}.reveal:not(.has-vertical-slides) .controls .navigate-left,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-left{bottom:1.4em;right:5.5em}.reveal:not(.has-vertical-slides) .controls .navigate-right,.reveal[data-navigation-mode=linear].has-horizontal-slides .navigate-right{bottom:1.4em;right:.5em}.reveal:not(.has-horizontal-slides) .controls .navigate-up{right:1.4em;bottom:5em}.reveal:not(.has-horizontal-slides) .controls .navigate-down{right:1.4em;bottom:.5em}.reveal.has-dark-background .controls{color:#fff}.reveal.has-light-background .controls{color:#000}.reveal.no-hover .controls .controls-arrow:active:before,.reveal.no-hover .controls .controls-arrow:hover:before{transform:translateX(.5em) translateY(1.55em) rotate(45deg)}.reveal.no-hover .controls .controls-arrow:active:after,.reveal.no-hover .controls .controls-arrow:hover:after{transform:translateX(.5em) translateY(1.55em) rotate(-45deg)}@media screen and (min-width:500px){.reveal-viewport{--r-controls-spacing:0.8em}.reveal .controls[data-controls-layout=edges]{top:0;right:0;bottom:0;left:0}.reveal .controls[data-controls-layout=edges] .navigate-down,.reveal .controls[data-controls-layout=edges] .navigate-left,.reveal .controls[data-controls-layout=edges] .navigate-right,.reveal .controls[data-controls-layout=edges] .navigate-up{bottom:auto;right:auto}.reveal .controls[data-controls-layout=edges] .navigate-left{top:50%;left:var(--r-controls-spacing);margin-top:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-right{top:50%;right:var(--r-controls-spacing);margin-top:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-up{top:var(--r-controls-spacing);left:50%;margin-left:-1.8em}.reveal .controls[data-controls-layout=edges] .navigate-down{bottom:calc(var(--r-controls-spacing) - 1.4em + .3em);left:50%;margin-left:-1.8em}}.reveal .progress{position:absolute;display:none;height:3px;width:100%;bottom:0;left:0;z-index:10;background-color:rgba(0,0,0,.2);color:#fff}.reveal .progress:after{content:"";display:block;position:absolute;height:10px;width:100%;top:-10px}.reveal .progress span{display:block;height:100%;width:100%;background-color:currentColor;transition:transform .8s cubic-bezier(.26,.86,.44,.985);transform-origin:0 0;transform:scaleX(0)}.reveal .slide-number{position:absolute;display:block;right:8px;bottom:8px;z-index:31;font-family:Helvetica,sans-serif;font-size:12px;line-height:1;color:#fff;background-color:rgba(0,0,0,.4);padding:5px}.reveal .slide-number a{color:currentColor}.reveal .slide-number-delimiter{margin:0 3px}.reveal{position:relative;width:100%;height:100%;overflow:hidden;touch-action:pinch-zoom}.reveal.embedded{touch-action:pan-y}.reveal .slides{position:absolute;width:100%;height:100%;top:0;right:0;bottom:0;left:0;margin:auto;pointer-events:none;overflow:visible;z-index:1;text-align:center;perspective:600px;perspective-origin:50% 40%}.reveal .slides>section{perspective:600px}.reveal .slides>section,.reveal .slides>section>section{display:none;position:absolute;width:100%;pointer-events:auto;z-index:10;transform-style:flat;transition:transform-origin .8s cubic-bezier(.26,.86,.44,.985),transform .8s cubic-bezier(.26,.86,.44,.985),visibility .8s cubic-bezier(.26,.86,.44,.985),opacity .8s cubic-bezier(.26,.86,.44,.985)}.reveal[data-transition-speed=fast] .slides section{transition-duration:.4s}.reveal[data-transition-speed=slow] .slides section{transition-duration:1.2s}.reveal .slides section[data-transition-speed=fast]{transition-duration:.4s}.reveal .slides section[data-transition-speed=slow]{transition-duration:1.2s}.reveal .slides>section.stack{padding-top:0;padding-bottom:0;pointer-events:none;height:100%}.reveal .slides>section.present,.reveal .slides>section>section.present{display:block;z-index:11;opacity:1}.reveal .slides>section:empty,.reveal .slides>section>section:empty,.reveal .slides>section>section[data-background-interactive],.reveal .slides>section[data-background-interactive]{pointer-events:none}.reveal.center,.reveal.center .slides,.reveal.center .slides section{min-height:0!important}.reveal .slides>section:not(.present),.reveal .slides>section>section:not(.present){pointer-events:none}.reveal.overview .slides>section,.reveal.overview .slides>section>section{pointer-events:auto}.reveal .slides>section.future,.reveal .slides>section.future>section,.reveal .slides>section.past,.reveal .slides>section.past>section,.reveal .slides>section>section.future,.reveal .slides>section>section.past{opacity:0}.reveal .slides>section[data-transition=slide].past,.reveal .slides>section[data-transition~=slide-out].past,.reveal.slide .slides>section:not([data-transition]).past{transform:translate(-150%,0)}.reveal .slides>section[data-transition=slide].future,.reveal .slides>section[data-transition~=slide-in].future,.reveal.slide .slides>section:not([data-transition]).future{transform:translate(150%,0)}.reveal .slides>section>section[data-transition=slide].past,.reveal .slides>section>section[data-transition~=slide-out].past,.reveal.slide .slides>section>section:not([data-transition]).past{transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=slide].future,.reveal .slides>section>section[data-transition~=slide-in].future,.reveal.slide .slides>section>section:not([data-transition]).future{transform:translate(0,150%)}.reveal .slides>section[data-transition=linear].past,.reveal .slides>section[data-transition~=linear-out].past,.reveal.linear .slides>section:not([data-transition]).past{transform:translate(-150%,0)}.reveal .slides>section[data-transition=linear].future,.reveal .slides>section[data-transition~=linear-in].future,.reveal.linear .slides>section:not([data-transition]).future{transform:translate(150%,0)}.reveal .slides>section>section[data-transition=linear].past,.reveal .slides>section>section[data-transition~=linear-out].past,.reveal.linear .slides>section>section:not([data-transition]).past{transform:translate(0,-150%)}.reveal .slides>section>section[data-transition=linear].future,.reveal .slides>section>section[data-transition~=linear-in].future,.reveal.linear .slides>section>section:not([data-transition]).future{transform:translate(0,150%)}.reveal .slides section[data-transition=default].stack,.reveal.default .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=default].past,.reveal .slides>section[data-transition~=default-out].past,.reveal.default .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=default].future,.reveal .slides>section[data-transition~=default-in].future,.reveal.default .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=default].past,.reveal .slides>section>section[data-transition~=default-out].past,.reveal.default .slides>section>section:not([data-transition]).past{transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=default].future,.reveal .slides>section>section[data-transition~=default-in].future,.reveal.default .slides>section>section:not([data-transition]).future{transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides section[data-transition=convex].stack,.reveal.convex .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=convex].past,.reveal .slides>section[data-transition~=convex-out].past,.reveal.convex .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=convex].future,.reveal .slides>section[data-transition~=convex-in].future,.reveal.convex .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=convex].past,.reveal .slides>section>section[data-transition~=convex-out].past,.reveal.convex .slides>section>section:not([data-transition]).past{transform:translate3d(0,-300px,0) rotateX(70deg) translate3d(0,-300px,0)}.reveal .slides>section>section[data-transition=convex].future,.reveal .slides>section>section[data-transition~=convex-in].future,.reveal.convex .slides>section>section:not([data-transition]).future{transform:translate3d(0,300px,0) rotateX(-70deg) translate3d(0,300px,0)}.reveal .slides section[data-transition=concave].stack,.reveal.concave .slides section.stack{transform-style:preserve-3d}.reveal .slides>section[data-transition=concave].past,.reveal .slides>section[data-transition~=concave-out].past,.reveal.concave .slides>section:not([data-transition]).past{transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal .slides>section[data-transition=concave].future,.reveal .slides>section[data-transition~=concave-in].future,.reveal.concave .slides>section:not([data-transition]).future{transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal .slides>section>section[data-transition=concave].past,.reveal .slides>section>section[data-transition~=concave-out].past,.reveal.concave .slides>section>section:not([data-transition]).past{transform:translate3d(0,-80%,0) rotateX(-70deg) translate3d(0,-80%,0)}.reveal .slides>section>section[data-transition=concave].future,.reveal .slides>section>section[data-transition~=concave-in].future,.reveal.concave .slides>section>section:not([data-transition]).future{transform:translate3d(0,80%,0) rotateX(70deg) translate3d(0,80%,0)}.reveal .slides section[data-transition=zoom],.reveal.zoom .slides section:not([data-transition]){transition-timing-function:ease}.reveal .slides>section[data-transition=zoom].past,.reveal .slides>section[data-transition~=zoom-out].past,.reveal.zoom .slides>section:not([data-transition]).past{visibility:hidden;transform:scale(16)}.reveal .slides>section[data-transition=zoom].future,.reveal .slides>section[data-transition~=zoom-in].future,.reveal.zoom .slides>section:not([data-transition]).future{visibility:hidden;transform:scale(.2)}.reveal .slides>section>section[data-transition=zoom].past,.reveal .slides>section>section[data-transition~=zoom-out].past,.reveal.zoom .slides>section>section:not([data-transition]).past{transform:scale(16)}.reveal .slides>section>section[data-transition=zoom].future,.reveal .slides>section>section[data-transition~=zoom-in].future,.reveal.zoom .slides>section>section:not([data-transition]).future{transform:scale(.2)}.reveal.cube .slides{perspective:1300px}.reveal.cube .slides section{padding:30px;min-height:700px;backface-visibility:hidden;box-sizing:border-box;transform-style:preserve-3d}.reveal.center.cube .slides section{min-height:0}.reveal.cube .slides section:not(.stack):before{content:"";position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);border-radius:4px;transform:translateZ(-20px)}.reveal.cube .slides section:not(.stack):after{content:"";position:absolute;display:block;width:90%;height:30px;left:5%;bottom:0;background:0 0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);transform:translateZ(-90px) rotateX(65deg)}.reveal.cube .slides>section.stack{padding:0;background:0 0}.reveal.cube .slides>section.past{transform-origin:100% 0;transform:translate3d(-100%,0,0) rotateY(-90deg)}.reveal.cube .slides>section.future{transform-origin:0 0;transform:translate3d(100%,0,0) rotateY(90deg)}.reveal.cube .slides>section>section.past{transform-origin:0 100%;transform:translate3d(0,-100%,0) rotateX(90deg)}.reveal.cube .slides>section>section.future{transform-origin:0 0;transform:translate3d(0,100%,0) rotateX(-90deg)}.reveal.page .slides{perspective-origin:0 50%;perspective:3000px}.reveal.page .slides section{padding:30px;min-height:700px;box-sizing:border-box;transform-style:preserve-3d}.reveal.page .slides section.past{z-index:12}.reveal.page .slides section:not(.stack):before{content:"";position:absolute;display:block;width:100%;height:100%;left:0;top:0;background:rgba(0,0,0,.1);transform:translateZ(-20px)}.reveal.page .slides section:not(.stack):after{content:"";position:absolute;display:block;width:90%;height:30px;left:5%;bottom:0;background:0 0;z-index:1;border-radius:4px;box-shadow:0 95px 25px rgba(0,0,0,.2);-webkit-transform:translateZ(-90px) rotateX(65deg)}.reveal.page .slides>section.stack{padding:0;background:0 0}.reveal.page .slides>section.past{transform-origin:0 0;transform:translate3d(-40%,0,0) rotateY(-80deg)}.reveal.page .slides>section.future{transform-origin:100% 0;transform:translate3d(0,0,0)}.reveal.page .slides>section>section.past{transform-origin:0 0;transform:translate3d(0,-40%,0) rotateX(80deg)}.reveal.page .slides>section>section.future{transform-origin:0 100%;transform:translate3d(0,0,0)}.reveal .slides section[data-transition=fade],.reveal.fade .slides section:not([data-transition]),.reveal.fade .slides>section>section:not([data-transition]){transform:none;transition:opacity .5s}.reveal.fade.overview .slides section,.reveal.fade.overview .slides>section>section{transition:none}.reveal .slides section[data-transition=none],.reveal.none .slides section:not([data-transition]){transform:none;transition:none}.reveal .pause-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:#000;visibility:hidden;opacity:0;z-index:100;transition:all 1s ease}.reveal .pause-overlay .resume-button{position:absolute;bottom:20px;right:20px;color:#ccc;border-radius:2px;padding:6px 14px;border:2px solid #ccc;font-size:16px;background:0 0;cursor:pointer}.reveal .pause-overlay .resume-button:hover{color:#fff;border-color:#fff}.reveal.paused .pause-overlay{visibility:visible;opacity:1}.reveal .no-transition,.reveal .no-transition *,.reveal .slides.disable-slide-transitions section{transition:none!important}.reveal .slides.disable-slide-transitions section{transform:none!important}.reveal .backgrounds{position:absolute;width:100%;height:100%;top:0;left:0;perspective:600px}.reveal .slide-background{display:none;position:absolute;width:100%;height:100%;opacity:0;visibility:hidden;overflow:hidden;background-color:rgba(0,0,0,0);transition:all .8s cubic-bezier(.26,.86,.44,.985)}.reveal .slide-background-content{position:absolute;width:100%;height:100%;background-position:50% 50%;background-repeat:no-repeat;background-size:cover}.reveal .slide-background.stack{display:block}.reveal .slide-background.present{opacity:1;visibility:visible;z-index:2}.print-pdf .reveal .slide-background{opacity:1!important;visibility:visible!important}.reveal .slide-background video{position:absolute;width:100%;height:100%;max-width:none;max-height:none;top:0;left:0;object-fit:cover}.reveal .slide-background[data-background-size=contain] video{object-fit:contain}.reveal>.backgrounds .slide-background[data-background-transition=none],.reveal[data-background-transition=none]>.backgrounds .slide-background:not([data-background-transition]){transition:none}.reveal>.backgrounds .slide-background[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background:not([data-background-transition]){opacity:1}.reveal>.backgrounds .slide-background.past[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background.past:not([data-background-transition]){transform:translate(-100%,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background.future:not([data-background-transition]){transform:translate(100%,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){transform:translate(0,-100%)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=slide],.reveal[data-background-transition=slide]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){transform:translate(0,100%)}.reveal>.backgrounds .slide-background.past[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(-100%,0,0) rotateY(-90deg) translate3d(-100%,0,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(100%,0,0) rotateY(90deg) translate3d(100%,0,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(0,-100%,0) rotateX(90deg) translate3d(0,-100%,0)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=convex],.reveal[data-background-transition=convex]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(0,100%,0) rotateX(-90deg) translate3d(0,100%,0)}.reveal>.backgrounds .slide-background.past[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(-100%,0,0) rotateY(90deg) translate3d(-100%,0,0)}.reveal>.backgrounds .slide-background.future[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(100%,0,0) rotateY(-90deg) translate3d(100%,0,0)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;transform:translate3d(0,-100%,0) rotateX(-90deg) translate3d(0,-100%,0)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=concave],.reveal[data-background-transition=concave]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;transform:translate3d(0,100%,0) rotateX(90deg) translate3d(0,100%,0)}.reveal>.backgrounds .slide-background[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background:not([data-background-transition]){transition-timing-function:ease}.reveal>.backgrounds .slide-background.past[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background.past:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(16)}.reveal>.backgrounds .slide-background.future[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background.future:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(.2)}.reveal>.backgrounds .slide-background>.slide-background.past[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.past:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(16)}.reveal>.backgrounds .slide-background>.slide-background.future[data-background-transition=zoom],.reveal[data-background-transition=zoom]>.backgrounds .slide-background>.slide-background.future:not([data-background-transition]){opacity:0;visibility:hidden;transform:scale(.2)}.reveal[data-transition-speed=fast]>.backgrounds .slide-background{transition-duration:.4s}.reveal[data-transition-speed=slow]>.backgrounds .slide-background{transition-duration:1.2s}.reveal [data-auto-animate-target^=unmatched]{will-change:opacity}.reveal section[data-auto-animate]:not(.stack):not([data-auto-animate=running]) [data-auto-animate-target^=unmatched]{opacity:0}.reveal.overview{perspective-origin:50% 50%;perspective:700px}.reveal.overview .slides{-moz-transform-style:preserve-3d}.reveal.overview .slides section{height:100%;top:0!important;opacity:1!important;overflow:hidden;visibility:visible!important;cursor:pointer;box-sizing:border-box}.reveal.overview .slides section.present,.reveal.overview .slides section:hover{outline:10px solid rgba(150,150,150,.4);outline-offset:10px}.reveal.overview .slides section .fragment{opacity:1;transition:none}.reveal.overview .slides section:after,.reveal.overview .slides section:before{display:none!important}.reveal.overview .slides>section.stack{padding:0;top:0!important;background:0 0;outline:0;overflow:visible}.reveal.overview .backgrounds{perspective:inherit;-moz-transform-style:preserve-3d}.reveal.overview .backgrounds .slide-background{opacity:1;visibility:visible;outline:10px solid rgba(150,150,150,.1);outline-offset:10px}.reveal.overview .backgrounds .slide-background.stack{overflow:visible}.reveal.overview .slides section,.reveal.overview-deactivating .slides section{transition:none}.reveal.overview .backgrounds .slide-background,.reveal.overview-deactivating .backgrounds .slide-background{transition:none}.reveal.rtl .slides,.reveal.rtl .slides h1,.reveal.rtl .slides h2,.reveal.rtl .slides h3,.reveal.rtl .slides h4,.reveal.rtl .slides h5,.reveal.rtl .slides h6{direction:rtl;font-family:sans-serif}.reveal.rtl code,.reveal.rtl pre{direction:ltr}.reveal.rtl ol,.reveal.rtl ul{text-align:right}.reveal.rtl .progress span{transform-origin:100% 0}.reveal.has-parallax-background .backgrounds{transition:all .8s ease}.reveal.has-parallax-background[data-transition-speed=fast] .backgrounds{transition-duration:.4s}.reveal.has-parallax-background[data-transition-speed=slow] .backgrounds{transition-duration:1.2s}.reveal>.overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(0,0,0,.95);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);transition:all .3s ease}.reveal>.overlay .spinner{position:absolute;display:block;top:50%;left:50%;width:32px;height:32px;margin:-16px 0 0 -16px;z-index:10;background-image:url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D);visibility:visible;opacity:.6;transition:all .3s ease}.reveal>.overlay header{position:absolute;left:0;top:0;width:100%;padding:5px;z-index:2;box-sizing:border-box}.reveal>.overlay header a{display:inline-block;width:40px;height:40px;line-height:36px;padding:0 10px;float:right;opacity:.6;box-sizing:border-box}.reveal>.overlay header a:hover{opacity:1}.reveal>.overlay header a .icon{display:inline-block;width:20px;height:20px;background-position:50% 50%;background-size:100%;background-repeat:no-repeat}.reveal>.overlay header a.close .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC)}.reveal>.overlay header a.external .icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==)}.reveal>.overlay .viewport{position:absolute;display:flex;top:50px;right:0;bottom:0;left:0}.reveal>.overlay.overlay-preview .viewport iframe{width:100%;height:100%;max-width:100%;max-height:100%;border:0;opacity:0;visibility:hidden;transition:all .3s ease}.reveal>.overlay.overlay-preview.loaded .viewport iframe{opacity:1;visibility:visible}.reveal>.overlay.overlay-preview.loaded .viewport-inner{position:absolute;z-index:-1;left:0;top:45%;width:100%;text-align:center;letter-spacing:normal}.reveal>.overlay.overlay-preview .x-frame-error{opacity:0;transition:opacity .3s ease .3s}.reveal>.overlay.overlay-preview.loaded .x-frame-error{opacity:1}.reveal>.overlay.overlay-preview.loaded .spinner{opacity:0;visibility:hidden;transform:scale(.2)}.reveal>.overlay.overlay-help .viewport{overflow:auto;color:#fff}.reveal>.overlay.overlay-help .viewport .viewport-inner{width:600px;margin:auto;padding:20px 20px 80px 20px;text-align:center;letter-spacing:normal}.reveal>.overlay.overlay-help .viewport .viewport-inner .title{font-size:20px}.reveal>.overlay.overlay-help .viewport .viewport-inner table{border:1px solid #fff;border-collapse:collapse;font-size:16px}.reveal>.overlay.overlay-help .viewport .viewport-inner table td,.reveal>.overlay.overlay-help .viewport .viewport-inner table th{width:200px;padding:14px;border:1px solid #fff;vertical-align:middle}.reveal>.overlay.overlay-help .viewport .viewport-inner table th{padding-top:20px;padding-bottom:20px}.reveal .playback{position:absolute;left:15px;bottom:20px;z-index:30;cursor:pointer;transition:all .4s ease;-webkit-tap-highlight-color:transparent}.reveal.overview .playback{opacity:0;visibility:hidden}.reveal .hljs{min-height:100%}.reveal .hljs table{margin:initial}.reveal .hljs-ln-code,.reveal .hljs-ln-numbers{padding:0;border:0}.reveal .hljs-ln-numbers{opacity:.6;padding-right:.75em;text-align:right;vertical-align:top}.reveal .hljs.has-highlights tr:not(.highlight-line){opacity:.4}.reveal .hljs.has-highlights.fragment{transition:all .2s ease}.reveal .hljs:not(:first-child).fragment{position:absolute;top:0;left:0;width:100%;box-sizing:border-box}.reveal pre[data-auto-animate-target]{overflow:hidden}.reveal pre[data-auto-animate-target] code{height:100%}.reveal .roll{display:inline-block;line-height:1.2;overflow:hidden;vertical-align:top;perspective:400px;perspective-origin:50% 50%}.reveal .roll:hover{background:0 0;text-shadow:none}.reveal .roll span{display:block;position:relative;padding:0 2px;pointer-events:none;transition:all .4s ease;transform-origin:50% 0;transform-style:preserve-3d;backface-visibility:hidden}.reveal .roll:hover span{background:rgba(0,0,0,.5);transform:translate3d(0,0,-45px) rotateX(90deg)}.reveal .roll span:after{content:attr(data-title);display:block;position:absolute;left:0;top:0;padding:0 2px;backface-visibility:hidden;transform-origin:50% 0;transform:translate3d(0,110%,0) rotateX(-90deg)}.reveal aside.notes{display:none}.reveal .speaker-notes{display:none;position:absolute;width:33.3333333333%;height:100%;top:0;left:100%;padding:14px 18px 14px 18px;z-index:1;font-size:18px;line-height:1.4;border:1px solid rgba(0,0,0,.05);color:#222;background-color:#f5f5f5;overflow:auto;box-sizing:border-box;text-align:left;font-family:Helvetica,sans-serif;-webkit-overflow-scrolling:touch}.reveal .speaker-notes .notes-placeholder{color:#ccc;font-style:italic}.reveal .speaker-notes:focus{outline:0}.reveal .speaker-notes:before{content:"Speaker notes";display:block;margin-bottom:10px;opacity:.5}.reveal.show-notes{max-width:75%;overflow:visible}.reveal.show-notes .speaker-notes{display:block}@media screen and (min-width:1600px){.reveal .speaker-notes{font-size:20px}}@media screen and (max-width:1024px){.reveal.show-notes{border-left:0;max-width:none;max-height:70%;max-height:70vh;overflow:visible}.reveal.show-notes .speaker-notes{top:100%;left:0;width:100%;height:30vh;border:0}}@media screen and (max-width:600px){.reveal.show-notes{max-height:60%;max-height:60vh}.reveal.show-notes .speaker-notes{top:100%;height:40vh}.reveal .speaker-notes{font-size:14px}}.reveal .jump-to-slide{position:absolute;top:15px;left:15px;z-index:30;font-size:32px;-webkit-tap-highlight-color:transparent}.reveal .jump-to-slide-input{background:0 0;padding:8px;font-size:inherit;color:currentColor;border:0}.reveal .jump-to-slide-input::placeholder{color:currentColor;opacity:.5}.reveal.has-dark-background .jump-to-slide-input{color:#fff}.reveal.has-light-background .jump-to-slide-input{color:#222}.reveal .jump-to-slide-input:focus{outline:0}.zoomed .reveal *,.zoomed .reveal :after,.zoomed .reveal :before{backface-visibility:visible!important}.zoomed .reveal .controls,.zoomed .reveal .progress{opacity:0}.zoomed .reveal .roll span{background:0 0}.zoomed .reveal .roll span:after{visibility:hidden}.reveal-viewport.loading-scroll-mode{visibility:hidden}.reveal-viewport.reveal-scroll{margin:0 auto;overflow:auto;overflow-x:hidden;overflow-y:auto;z-index:1;--r-scrollbar-width:7px;--r-scrollbar-trigger-size:5px;--r-controls-spacing:8px}@media screen and (max-width:500px){.reveal-viewport.reveal-scroll{--r-scrollbar-width:3px;--r-scrollbar-trigger-size:3px}}.reveal-viewport.reveal-scroll .backgrounds,.reveal-viewport.reveal-scroll .controls,.reveal-viewport.reveal-scroll .playback,.reveal-viewport.reveal-scroll .progress,.reveal-viewport.reveal-scroll .slide-number,.reveal-viewport.reveal-scroll .speaker-notes{display:none!important}.reveal-viewport.reveal-scroll .overlay,.reveal-viewport.reveal-scroll .pause-overlay{position:fixed}.reveal-viewport.reveal-scroll .reveal{overflow:visible;touch-action:manipulation}.reveal-viewport.reveal-scroll .slides{position:static;pointer-events:initial;left:auto;top:auto;width:100%!important;margin:0;padding:0;overflow:visible;display:block;perspective:none;perspective-origin:50% 50%}.reveal-viewport.reveal-scroll .scroll-page{position:relative;width:100%;height:calc(var(--page-height) + var(--page-scroll-padding));z-index:1;overflow:visible}.reveal-viewport.reveal-scroll .scroll-page-sticky{position:sticky;height:var(--page-height);top:0}.reveal-viewport.reveal-scroll .scroll-page-content{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden}.reveal-viewport.reveal-scroll .scroll-page section{visibility:visible!important;display:block!important;position:absolute!important;width:var(--slide-width)!important;height:var(--slide-height)!important;top:50%!important;left:50%!important;opacity:1!important;transform:scale(var(--slide-scale)) translate(-50%,-50%)!important;transform-style:flat!important;transform-origin:0 0!important}.reveal-viewport.reveal-scroll .slide-background{display:block!important;position:absolute;top:0;left:0;width:100%;height:100%;z-index:auto!important;visibility:visible;opacity:1;touch-action:manipulation}.reveal-viewport.reveal-scroll[data-scrollbar=auto]::-webkit-scrollbar,.reveal-viewport.reveal-scroll[data-scrollbar=true]::-webkit-scrollbar{display:none}.reveal-viewport.reveal-scroll[data-scrollbar=auto],.reveal-viewport.reveal-scroll[data-scrollbar=true]{scrollbar-width:none}.reveal-viewport.has-dark-background,.reveal.has-dark-background{--r-overlay-element-bg-color:240,240,240;--r-overlay-element-fg-color:0,0,0}.reveal-viewport.has-light-background,.reveal.has-light-background{--r-overlay-element-bg-color:0,0,0;--r-overlay-element-fg-color:240,240,240}.reveal-viewport.reveal-scroll .scrollbar{position:sticky;top:50%;z-index:20;opacity:0;transition:all .3s ease}.reveal-viewport.reveal-scroll .scrollbar.visible,.reveal-viewport.reveal-scroll .scrollbar:hover{opacity:1}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-inner{position:absolute;width:var(--r-scrollbar-width);height:calc(var(--viewport-height) - var(--r-controls-spacing) * 2);right:var(--r-controls-spacing);top:0;transform:translateY(-50%);border-radius:var(--r-scrollbar-width);z-index:10}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-playhead{position:absolute;width:var(--r-scrollbar-width);height:var(--r-scrollbar-width);top:0;left:0;border-radius:var(--r-scrollbar-width);background-color:rgba(var(--r-overlay-element-bg-color),1);z-index:11;transition:background-color .2s ease}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide{position:absolute;width:100%;background-color:rgba(var(--r-overlay-element-bg-color),.2);box-shadow:0 0 0 1px rgba(var(--r-overlay-element-fg-color),.1);border-radius:var(--r-scrollbar-width);transition:background-color .2s ease}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide:after{content:"";position:absolute;width:200%;height:100%;top:0;left:-50%;background:rgba(0,0,0,0);z-index:-1}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active,.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide:hover{background-color:rgba(var(--r-overlay-element-bg-color),.4)}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-trigger{position:absolute;width:100%;transition:background-color .2s ease}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active.has-triggers{background-color:rgba(var(--r-overlay-element-bg-color),.4);z-index:10}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger:after{content:"";position:absolute;width:var(--r-scrollbar-trigger-size);height:var(--r-scrollbar-trigger-size);border-radius:20px;top:50%;left:50%;transform:translate(-50%,-50%);background-color:rgba(var(--r-overlay-element-bg-color),1);transition:transform .2s ease,opacity .2s ease;opacity:.4}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger.active:after,.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger.active~.scrollbar-trigger:after{opacity:1}.reveal-viewport.reveal-scroll .scrollbar .scrollbar-slide.active .scrollbar-trigger~.scrollbar-trigger.active:after{transform:translate(calc(var(--r-scrollbar-width) * -2),0);background-color:rgba(var(--r-overlay-element-bg-color),1)}html.reveal-print *{-webkit-print-color-adjust:exact}html.reveal-print{width:100%;height:100%;overflow:visible}html.reveal-print body{margin:0 auto!important;border:0;padding:0;float:none!important;overflow:visible}html.reveal-print .nestedarrow,html.reveal-print .reveal .controls,html.reveal-print .reveal .playback,html.reveal-print .reveal .progress,html.reveal-print .reveal.overview,html.reveal-print .state-background{display:none!important}html.reveal-print .reveal pre code{overflow:hidden!important}html.reveal-print .reveal{width:auto!important;height:auto!important;overflow:hidden!important}html.reveal-print .reveal .slides{position:static;width:100%!important;height:auto!important;zoom:1!important;pointer-events:initial;left:auto;top:auto;margin:0!important;padding:0!important;overflow:visible;display:block;perspective:none;perspective-origin:50% 50%}html.reveal-print .reveal .slides .pdf-page{position:relative;overflow:hidden;z-index:1;page-break-after:always}html.reveal-print .reveal .slides .pdf-page:last-of-type{page-break-after:avoid}html.reveal-print .reveal .slides section{visibility:visible!important;display:block!important;position:absolute!important;margin:0!important;padding:0!important;box-sizing:border-box!important;min-height:1px;opacity:1!important;transform-style:flat!important;transform:none!important}html.reveal-print .reveal section.stack{position:relative!important;margin:0!important;padding:0!important;page-break-after:avoid!important;height:auto!important;min-height:auto!important}html.reveal-print .reveal img{box-shadow:none}html.reveal-print .reveal .backgrounds{display:none}html.reveal-print .reveal .slide-background{display:block!important;position:absolute;top:0;left:0;width:100%;height:100%;z-index:auto!important}html.reveal-print .reveal.show-notes{max-width:none;max-height:none}html.reveal-print .reveal .speaker-notes-pdf{display:block;width:100%;height:auto;max-height:none;top:auto;right:auto;bottom:auto;left:auto;z-index:100}html.reveal-print .reveal .speaker-notes-pdf[data-layout=separate-page]{position:relative;color:inherit;background-color:transparent;padding:20px;page-break-after:always;border:0}html.reveal-print .reveal .slide-number-pdf{display:block;position:absolute;font-size:14px;visibility:visible}html.reveal-print .aria-status{display:none}@media print{html:not(.print-pdf){overflow:visible;width:auto;height:auto}html:not(.print-pdf) body{margin:0;padding:0;overflow:visible}html:not(.print-pdf) .reveal{background:#fff;font-size:20pt}html:not(.print-pdf) .reveal .backgrounds,html:not(.print-pdf) .reveal .controls,html:not(.print-pdf) .reveal .progress,html:not(.print-pdf) .reveal .slide-number,html:not(.print-pdf) .reveal .state-background{display:none!important}html:not(.print-pdf) .reveal li,html:not(.print-pdf) .reveal p,html:not(.print-pdf) .reveal td{font-size:20pt!important;color:#000}html:not(.print-pdf) .reveal h1,html:not(.print-pdf) .reveal h2,html:not(.print-pdf) .reveal h3,html:not(.print-pdf) .reveal h4,html:not(.print-pdf) .reveal h5,html:not(.print-pdf) .reveal h6{color:#000!important;height:auto;line-height:normal;text-align:left;letter-spacing:normal}html:not(.print-pdf) .reveal h1{font-size:28pt!important}html:not(.print-pdf) .reveal h2{font-size:24pt!important}html:not(.print-pdf) .reveal h3{font-size:22pt!important}html:not(.print-pdf) .reveal h4{font-size:22pt!important;font-variant:small-caps}html:not(.print-pdf) .reveal h5{font-size:21pt!important}html:not(.print-pdf) .reveal h6{font-size:20pt!important;font-style:italic}html:not(.print-pdf) .reveal a:link,html:not(.print-pdf) .reveal a:visited{color:#000!important;font-weight:700;text-decoration:underline}html:not(.print-pdf) .reveal div,html:not(.print-pdf) .reveal ol,html:not(.print-pdf) .reveal p,html:not(.print-pdf) .reveal ul{visibility:visible;position:static;width:auto;height:auto;display:block;overflow:visible;margin:0;text-align:left!important}html:not(.print-pdf) .reveal pre,html:not(.print-pdf) .reveal table{margin-left:0;margin-right:0}html:not(.print-pdf) .reveal pre code{padding:20px}html:not(.print-pdf) .reveal blockquote{margin:20px 0}html:not(.print-pdf) .reveal .slides{position:static!important;width:auto!important;height:auto!important;left:0!important;top:0!important;margin-left:0!important;margin-top:0!important;padding:0!important;zoom:1!important;transform:none!important;overflow:visible!important;display:block!important;text-align:left!important;perspective:none;perspective-origin:50% 50%}html:not(.print-pdf) .reveal .slides section{visibility:visible!important;position:static!important;width:auto!important;height:auto!important;display:block!important;overflow:visible!important;left:0!important;top:0!important;margin-left:0!important;margin-top:0!important;padding:60px 20px!important;z-index:auto!important;opacity:1!important;page-break-after:always!important;transform-style:flat!important;transform:none!important;transition:none!important}html:not(.print-pdf) .reveal .slides section.stack{padding:0!important}html:not(.print-pdf) .reveal .slides section:last-of-type{page-break-after:avoid!important}html:not(.print-pdf) .reveal .slides section .fragment{opacity:1!important;visibility:visible!important;transform:none!important}html:not(.print-pdf) .reveal .r-fit-text{white-space:normal!important}html:not(.print-pdf) .reveal section img{display:block;margin:15px 0;background:#fff;border:1px solid #666;box-shadow:none}html:not(.print-pdf) .reveal section small{font-size:.8em}html:not(.print-pdf) .reveal .hljs{max-height:100%;white-space:pre-wrap;word-wrap:break-word;word-break:break-word;font-size:15pt}html:not(.print-pdf) .reveal .hljs .hljs-ln-numbers{white-space:nowrap}html:not(.print-pdf) .reveal .hljs td{font-size:inherit!important;color:inherit!important}} \ No newline at end of file diff --git a/src/public/bash/dist/reveal.esm.js b/src/public/bash/dist/reveal.esm.js new file mode 100644 index 0000000..fca65e9 --- /dev/null +++ b/src/public/bash/dist/reveal.esm.js @@ -0,0 +1,9 @@ +/*! +* reveal.js 5.0.5 +* https://revealjs.com +* MIT licensed +* +* Copyright (C) 2011-2024 Hakim El Hattab, https://hakim.se +*/ +const e=(e,t)=>{for(let i in t)e[i]=t[i];return e},t=(e,t)=>Array.from(e.querySelectorAll(t)),i=(e,t,i)=>{i?e.classList.add(t):e.classList.remove(t)},s=e=>{if("string"==typeof e){if("null"===e)return null;if("true"===e)return!0;if("false"===e)return!1;if(e.match(/^-?[\d\.]+$/))return parseFloat(e)}return e},a=(e,t)=>{e.style.transform=t},n=(e,t)=>{let i=e.matches||e.matchesSelector||e.msMatchesSelector;return!(!i||!i.call(e,t))},r=(e,t)=>{if("function"==typeof e.closest)return e.closest(t);for(;e;){if(n(e,t))return e;e=e.parentNode}return null},o=e=>{let t=(e=e||document.documentElement).requestFullscreen||e.webkitRequestFullscreen||e.webkitRequestFullScreen||e.mozRequestFullScreen||e.msRequestFullscreen;t&&t.apply(e)},l=e=>{let t=document.createElement("style");return t.type="text/css",e&&e.length>0&&(t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e))),document.head.appendChild(t),t},d=()=>{let e={};location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi,(t=>{e[t.split("=").shift()]=t.split("=").pop()}));for(let t in e){let i=e[t];e[t]=s(unescape(i))}return void 0!==e.dependencies&&delete e.dependencies,e},c={mp4:"video/mp4",m4a:"video/mp4",ogv:"video/ogg",mpeg:"video/mpeg",webm:"video/webm"},h=navigator.userAgent,u=/(iphone|ipod|ipad|android)/gi.test(h)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1,g=/android/gi.test(h);var p=function(e){if(e){var t=function(e){return[].slice.call(e)},i=3,s=[],a=null,n="requestAnimationFrame"in e?function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{sync:!1};e.cancelAnimationFrame(a);var i=function(){return o(s.filter((function(e){return e.dirty&&e.active})))};if(t.sync)return i();a=e.requestAnimationFrame(i)}:function(){},r=function(e){return function(t){s.forEach((function(t){return t.dirty=e})),n(t)}},o=function(e){e.filter((function(e){return!e.styleComputed})).forEach((function(e){e.styleComputed=h(e)})),e.filter(u).forEach(g);var t=e.filter(c);t.forEach(d),t.forEach((function(e){g(e),l(e)})),t.forEach(p)},l=function(e){return e.dirty=0},d=function(e){e.availableWidth=e.element.parentNode.clientWidth,e.currentWidth=e.element.scrollWidth,e.previousFontSize=e.currentFontSize,e.currentFontSize=Math.min(Math.max(e.minSize,e.availableWidth/e.currentWidth*e.previousFontSize),e.maxSize),e.whiteSpace=e.multiLine&&e.currentFontSize===e.minSize?"normal":"nowrap"},c=function(e){return 2!==e.dirty||2===e.dirty&&e.element.parentNode.clientWidth!==e.availableWidth},h=function(t){var i=e.getComputedStyle(t.element,null);return t.currentFontSize=parseFloat(i.getPropertyValue("font-size")),t.display=i.getPropertyValue("display"),t.whiteSpace=i.getPropertyValue("white-space"),!0},u=function(e){var t=!1;return!e.preStyleTestCompleted&&(/inline-/.test(e.display)||(t=!0,e.display="inline-block"),"nowrap"!==e.whiteSpace&&(t=!0,e.whiteSpace="nowrap"),e.preStyleTestCompleted=!0,t)},g=function(e){e.element.style.whiteSpace=e.whiteSpace,e.element.style.display=e.display,e.element.style.fontSize=e.currentFontSize+"px"},p=function(e){e.element.dispatchEvent(new CustomEvent("fit",{detail:{oldValue:e.previousFontSize,newValue:e.currentFontSize,scaleFactor:e.currentFontSize/e.previousFontSize}}))},v=function(e,t){return function(i){e.dirty=t,e.active&&n(i)}},m=function(e){return function(){s=s.filter((function(t){return t.element!==e.element})),e.observeMutations&&e.observer.disconnect(),e.element.style.whiteSpace=e.originalStyle.whiteSpace,e.element.style.display=e.originalStyle.display,e.element.style.fontSize=e.originalStyle.fontSize}},f=function(e){return function(){e.active||(e.active=!0,n())}},y=function(e){return function(){return e.active=!1}},b=function(e){e.observeMutations&&(e.observer=new MutationObserver(v(e,1)),e.observer.observe(e.element,e.observeMutations))},w={minSize:16,maxSize:512,multiLine:!0,observeMutations:"MutationObserver"in e&&{subtree:!0,childList:!0,characterData:!0}},E=null,S=function(){e.clearTimeout(E),E=e.setTimeout(r(2),k.observeWindowDelay)},A=["resize","orientationchange"];return Object.defineProperty(k,"observeWindow",{set:function(t){var i="".concat(t?"add":"remove","EventListener");A.forEach((function(t){e[i](t,S)}))}}),k.observeWindow=!0,k.observeWindowDelay=100,k.fitAll=r(i),k}function R(e,t){var a=Object.assign({},w,t),r=e.map((function(e){var t=Object.assign({},a,{element:e,active:!0});return function(e){e.originalStyle={whiteSpace:e.element.style.whiteSpace,display:e.element.style.display,fontSize:e.element.style.fontSize},b(e),e.newbie=!0,e.dirty=!0,s.push(e)}(t),{element:e,fit:v(t,i),unfreeze:f(t),freeze:y(t),unsubscribe:m(t)}}));return n(),r}function k(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return"string"==typeof e?R(t(document.querySelectorAll(e)),i):R([e],i)[0]}}("undefined"==typeof window?null:window);class v{constructor(e){this.Reveal=e,this.startEmbeddedIframe=this.startEmbeddedIframe.bind(this)}shouldPreload(e){if(this.Reveal.isScrollView())return!0;let t=this.Reveal.getConfig().preloadIframes;return"boolean"!=typeof t&&(t=e.hasAttribute("data-preload")),t}load(e,i={}){e.style.display=this.Reveal.getConfig().display,t(e,"img[data-src], video[data-src], audio[data-src], iframe[data-src]").forEach((e=>{("IFRAME"!==e.tagName||this.shouldPreload(e))&&(e.setAttribute("src",e.getAttribute("data-src")),e.setAttribute("data-lazy-loaded",""),e.removeAttribute("data-src"))})),t(e,"video, audio").forEach((e=>{let i=0;t(e,"source[data-src]").forEach((e=>{e.setAttribute("src",e.getAttribute("data-src")),e.removeAttribute("data-src"),e.setAttribute("data-lazy-loaded",""),i+=1})),u&&"VIDEO"===e.tagName&&e.setAttribute("playsinline",""),i>0&&e.load()}));let s=e.slideBackgroundElement;if(s){s.style.display="block";let t=e.slideBackgroundContentElement,a=e.getAttribute("data-background-iframe");if(!1===s.hasAttribute("data-loaded")){s.setAttribute("data-loaded","true");let n=e.getAttribute("data-background-image"),r=e.getAttribute("data-background-video"),o=e.hasAttribute("data-background-video-loop"),l=e.hasAttribute("data-background-video-muted");if(n)/^data:/.test(n.trim())?t.style.backgroundImage=`url(${n.trim()})`:t.style.backgroundImage=n.split(",").map((e=>`url(${((e="")=>encodeURI(e).replace(/%5B/g,"[").replace(/%5D/g,"]").replace(/[!'()*]/g,(e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`)))(decodeURI(e.trim()))})`)).join(",");else if(r&&!this.Reveal.isSpeakerNotes()){let e=document.createElement("video");o&&e.setAttribute("loop",""),l&&(e.muted=!0),u&&(e.muted=!0,e.setAttribute("playsinline","")),r.split(",").forEach((t=>{const i=document.createElement("source");i.setAttribute("src",t);let s=((e="")=>c[e.split(".").pop()])(t);s&&i.setAttribute("type",s),e.appendChild(i)})),t.appendChild(e)}else if(a&&!0!==i.excludeIframes){let e=document.createElement("iframe");e.setAttribute("allowfullscreen",""),e.setAttribute("mozallowfullscreen",""),e.setAttribute("webkitallowfullscreen",""),e.setAttribute("allow","autoplay"),e.setAttribute("data-src",a),e.style.width="100%",e.style.height="100%",e.style.maxHeight="100%",e.style.maxWidth="100%",t.appendChild(e)}}let n=t.querySelector("iframe[data-src]");n&&this.shouldPreload(s)&&!/autoplay=(1|true|yes)/gi.test(a)&&n.getAttribute("src")!==a&&n.setAttribute("src",a)}this.layout(e)}layout(e){Array.from(e.querySelectorAll(".r-fit-text")).forEach((e=>{p(e,{minSize:24,maxSize:.8*this.Reveal.getConfig().height,observeMutations:!1,observeWindow:!1})}))}unload(e){e.style.display="none";let i=this.Reveal.getSlideBackground(e);i&&(i.style.display="none",t(i,"iframe[src]").forEach((e=>{e.removeAttribute("src")}))),t(e,"video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]").forEach((e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")})),t(e,"video[data-lazy-loaded] source[src], audio source[src]").forEach((e=>{e.setAttribute("data-src",e.getAttribute("src")),e.removeAttribute("src")}))}formatEmbeddedContent(){let e=(e,i,s)=>{t(this.Reveal.getSlidesElement(),"iframe["+e+'*="'+i+'"]').forEach((t=>{let i=t.getAttribute(e);i&&-1===i.indexOf(s)&&t.setAttribute(e,i+(/\?/.test(i)?"&":"?")+s)}))};e("src","youtube.com/embed/","enablejsapi=1"),e("data-src","youtube.com/embed/","enablejsapi=1"),e("src","player.vimeo.com/","api=1"),e("data-src","player.vimeo.com/","api=1")}startEmbeddedContent(e){e&&!this.Reveal.isSpeakerNotes()&&(t(e,'img[src$=".gif"]').forEach((e=>{e.setAttribute("src",e.getAttribute("src"))})),t(e,"video, audio").forEach((e=>{if(r(e,".fragment")&&!r(e,".fragment.visible"))return;let t=this.Reveal.getConfig().autoPlayMedia;if("boolean"!=typeof t&&(t=e.hasAttribute("data-autoplay")||!!r(e,".slide-background")),t&&"function"==typeof e.play)if(e.readyState>1)this.startEmbeddedMedia({target:e});else if(u){let t=e.play();t&&"function"==typeof t.catch&&!1===e.controls&&t.catch((()=>{e.controls=!0,e.addEventListener("play",(()=>{e.controls=!1}))}))}else e.removeEventListener("loadeddata",this.startEmbeddedMedia),e.addEventListener("loadeddata",this.startEmbeddedMedia)})),t(e,"iframe[src]").forEach((e=>{r(e,".fragment")&&!r(e,".fragment.visible")||this.startEmbeddedIframe({target:e})})),t(e,"iframe[data-src]").forEach((e=>{r(e,".fragment")&&!r(e,".fragment.visible")||e.getAttribute("src")!==e.getAttribute("data-src")&&(e.removeEventListener("load",this.startEmbeddedIframe),e.addEventListener("load",this.startEmbeddedIframe),e.setAttribute("src",e.getAttribute("data-src")))})))}startEmbeddedMedia(e){let t=!!r(e.target,"html"),i=!!r(e.target,".present");t&&i&&(e.target.currentTime=0,e.target.play()),e.target.removeEventListener("loadeddata",this.startEmbeddedMedia)}startEmbeddedIframe(e){let t=e.target;if(t&&t.contentWindow){let i=!!r(e.target,"html"),s=!!r(e.target,".present");if(i&&s){let e=this.Reveal.getConfig().autoPlayMedia;"boolean"!=typeof e&&(e=t.hasAttribute("data-autoplay")||!!r(t,".slide-background")),/youtube\.com\/embed\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}',"*"):/player\.vimeo\.com\//.test(t.getAttribute("src"))&&e?t.contentWindow.postMessage('{"method":"play"}',"*"):t.contentWindow.postMessage("slide:start","*")}}}stopEmbeddedContent(i,s={}){s=e({unloadIframes:!0},s),i&&i.parentNode&&(t(i,"video, audio").forEach((e=>{e.hasAttribute("data-ignore")||"function"!=typeof e.pause||(e.setAttribute("data-paused-by-reveal",""),e.pause())})),t(i,"iframe").forEach((e=>{e.contentWindow&&e.contentWindow.postMessage("slide:stop","*"),e.removeEventListener("load",this.startEmbeddedIframe)})),t(i,'iframe[src*="youtube.com/embed/"]').forEach((e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}',"*")})),t(i,'iframe[src*="player.vimeo.com/"]').forEach((e=>{!e.hasAttribute("data-ignore")&&e.contentWindow&&"function"==typeof e.contentWindow.postMessage&&e.contentWindow.postMessage('{"method":"pause"}',"*")})),!0===s.unloadIframes&&t(i,"iframe[data-src]").forEach((e=>{e.setAttribute("src","about:blank"),e.removeAttribute("src")})))}}const m=".slides section",f=".slides>section",y=".slides>section.present>section",b=/registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/,w=/fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;class E{constructor(e){this.Reveal=e}render(){this.element=document.createElement("div"),this.element.className="slide-number",this.Reveal.getRevealElement().appendChild(this.element)}configure(e,t){let i="none";e.slideNumber&&!this.Reveal.isPrintView()&&("all"===e.showSlideNumber||"speaker"===e.showSlideNumber&&this.Reveal.isSpeakerNotes())&&(i="block"),this.element.style.display=i}update(){this.Reveal.getConfig().slideNumber&&this.element&&(this.element.innerHTML=this.getSlideNumber())}getSlideNumber(e=this.Reveal.getCurrentSlide()){let t,i=this.Reveal.getConfig(),s="h.v";if("function"==typeof i.slideNumber)t=i.slideNumber(e);else{"string"==typeof i.slideNumber&&(s=i.slideNumber),/c/.test(s)||1!==this.Reveal.getHorizontalSlides().length||(s="c");let a=e&&"uncounted"===e.dataset.visibility?0:1;switch(t=[],s){case"c":t.push(this.Reveal.getSlidePastCount(e)+a);break;case"c/t":t.push(this.Reveal.getSlidePastCount(e)+a,"/",this.Reveal.getTotalSlides());break;default:let i=this.Reveal.getIndices(e);t.push(i.h+a);let n="h/v"===s?"/":".";this.Reveal.isVerticalSlide(e)&&t.push(n,i.v+1)}}let a="#"+this.Reveal.location.getHash(e);return this.formatNumber(t[0],t[1],t[2],a)}formatNumber(e,t,i,s="#"+this.Reveal.location.getHash()){return"number"!=typeof i||isNaN(i)?`\n\t\t\t\t\t${e}\n\t\t\t\t\t`:`\n\t\t\t\t\t${e}\n\t\t\t\t\t${t}\n\t\t\t\t\t${i}\n\t\t\t\t\t`}destroy(){this.element.remove()}}class S{constructor(e){this.Reveal=e,this.onInput=this.onInput.bind(this),this.onBlur=this.onBlur.bind(this),this.onKeyDown=this.onKeyDown.bind(this)}render(){this.element=document.createElement("div"),this.element.className="jump-to-slide",this.jumpInput=document.createElement("input"),this.jumpInput.type="text",this.jumpInput.className="jump-to-slide-input",this.jumpInput.placeholder="Jump to slide",this.jumpInput.addEventListener("input",this.onInput),this.jumpInput.addEventListener("keydown",this.onKeyDown),this.jumpInput.addEventListener("blur",this.onBlur),this.element.appendChild(this.jumpInput)}show(){this.indicesOnShow=this.Reveal.getIndices(),this.Reveal.getRevealElement().appendChild(this.element),this.jumpInput.focus()}hide(){this.isVisible()&&(this.element.remove(),this.jumpInput.value="",clearTimeout(this.jumpTimeout),delete this.jumpTimeout)}isVisible(){return!!this.element.parentNode}jump(){clearTimeout(this.jumpTimeout),delete this.jumpTimeout;let e,t=this.jumpInput.value.trim("");if(/^\d+$/.test(t)){const i=this.Reveal.getConfig().slideNumber;if("c"===i||"c/t"===i){const i=this.Reveal.getSlides()[parseInt(t,10)-1];i&&(e=this.Reveal.getIndices(i))}}return e||(/^\d+\.\d+$/.test(t)&&(t=t.replace(".","/")),e=this.Reveal.location.getIndicesFromHash(t,{oneBasedIndex:!0})),!e&&/\S+/i.test(t)&&t.length>1&&(e=this.search(t)),e&&""!==t?(this.Reveal.slide(e.h,e.v,e.f),!0):(this.Reveal.slide(this.indicesOnShow.h,this.indicesOnShow.v,this.indicesOnShow.f),!1)}jumpAfter(e){clearTimeout(this.jumpTimeout),this.jumpTimeout=setTimeout((()=>this.jump()),e)}search(e){const t=new RegExp("\\b"+e.trim()+"\\b","i"),i=this.Reveal.getSlides().find((e=>t.test(e.innerText)));return i?this.Reveal.getIndices(i):null}cancel(){this.Reveal.slide(this.indicesOnShow.h,this.indicesOnShow.v,this.indicesOnShow.f),this.hide()}confirm(){this.jump(),this.hide()}destroy(){this.jumpInput.removeEventListener("input",this.onInput),this.jumpInput.removeEventListener("keydown",this.onKeyDown),this.jumpInput.removeEventListener("blur",this.onBlur),this.element.remove()}onKeyDown(e){13===e.keyCode?this.confirm():27===e.keyCode&&(this.cancel(),e.stopImmediatePropagation())}onInput(e){this.jumpAfter(200)}onBlur(){setTimeout((()=>this.hide()),1)}}const A=e=>{let t=e.match(/^#([0-9a-f]{3})$/i);if(t&&t[1])return t=t[1],{r:17*parseInt(t.charAt(0),16),g:17*parseInt(t.charAt(1),16),b:17*parseInt(t.charAt(2),16)};let i=e.match(/^#([0-9a-f]{6})$/i);if(i&&i[1])return i=i[1],{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)};let s=e.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);if(s)return{r:parseInt(s[1],10),g:parseInt(s[2],10),b:parseInt(s[3],10)};let a=e.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\,\s*([\d]+|[\d]*.[\d]+)\s*\)$/i);return a?{r:parseInt(a[1],10),g:parseInt(a[2],10),b:parseInt(a[3],10),a:parseFloat(a[4])}:null};class R{constructor(e){this.Reveal=e}render(){this.element=document.createElement("div"),this.element.className="backgrounds",this.Reveal.getRevealElement().appendChild(this.element)}create(){this.element.innerHTML="",this.element.classList.add("no-transition"),this.Reveal.getHorizontalSlides().forEach((e=>{let i=this.createBackground(e,this.element);t(e,"section").forEach((e=>{this.createBackground(e,i),i.classList.add("stack")}))})),this.Reveal.getConfig().parallaxBackgroundImage?(this.element.style.backgroundImage='url("'+this.Reveal.getConfig().parallaxBackgroundImage+'")',this.element.style.backgroundSize=this.Reveal.getConfig().parallaxBackgroundSize,this.element.style.backgroundRepeat=this.Reveal.getConfig().parallaxBackgroundRepeat,this.element.style.backgroundPosition=this.Reveal.getConfig().parallaxBackgroundPosition,setTimeout((()=>{this.Reveal.getRevealElement().classList.add("has-parallax-background")}),1)):(this.element.style.backgroundImage="",this.Reveal.getRevealElement().classList.remove("has-parallax-background"))}createBackground(e,t){let i=document.createElement("div");i.className="slide-background "+e.className.replace(/present|past|future/,"");let s=document.createElement("div");return s.className="slide-background-content",i.appendChild(s),t.appendChild(i),e.slideBackgroundElement=i,e.slideBackgroundContentElement=s,this.sync(e),i}sync(e){const t=e.slideBackgroundElement,i=e.slideBackgroundContentElement,s={background:e.getAttribute("data-background"),backgroundSize:e.getAttribute("data-background-size"),backgroundImage:e.getAttribute("data-background-image"),backgroundVideo:e.getAttribute("data-background-video"),backgroundIframe:e.getAttribute("data-background-iframe"),backgroundColor:e.getAttribute("data-background-color"),backgroundGradient:e.getAttribute("data-background-gradient"),backgroundRepeat:e.getAttribute("data-background-repeat"),backgroundPosition:e.getAttribute("data-background-position"),backgroundTransition:e.getAttribute("data-background-transition"),backgroundOpacity:e.getAttribute("data-background-opacity")},a=e.hasAttribute("data-preload");e.classList.remove("has-dark-background"),e.classList.remove("has-light-background"),t.removeAttribute("data-loaded"),t.removeAttribute("data-background-hash"),t.removeAttribute("data-background-size"),t.removeAttribute("data-background-transition"),t.style.backgroundColor="",i.style.backgroundSize="",i.style.backgroundRepeat="",i.style.backgroundPosition="",i.style.backgroundImage="",i.style.opacity="",i.innerHTML="",s.background&&(/^(http|file|\/\/)/gi.test(s.background)||/\.(svg|png|jpg|jpeg|gif|bmp|webp)([?#\s]|$)/gi.test(s.background)?e.setAttribute("data-background-image",s.background):t.style.background=s.background),(s.background||s.backgroundColor||s.backgroundGradient||s.backgroundImage||s.backgroundVideo||s.backgroundIframe)&&t.setAttribute("data-background-hash",s.background+s.backgroundSize+s.backgroundImage+s.backgroundVideo+s.backgroundIframe+s.backgroundColor+s.backgroundGradient+s.backgroundRepeat+s.backgroundPosition+s.backgroundTransition+s.backgroundOpacity),s.backgroundSize&&t.setAttribute("data-background-size",s.backgroundSize),s.backgroundColor&&(t.style.backgroundColor=s.backgroundColor),s.backgroundGradient&&(t.style.backgroundImage=s.backgroundGradient),s.backgroundTransition&&t.setAttribute("data-background-transition",s.backgroundTransition),a&&t.setAttribute("data-preload",""),s.backgroundSize&&(i.style.backgroundSize=s.backgroundSize),s.backgroundRepeat&&(i.style.backgroundRepeat=s.backgroundRepeat),s.backgroundPosition&&(i.style.backgroundPosition=s.backgroundPosition),s.backgroundOpacity&&(i.style.opacity=s.backgroundOpacity);const n=this.getContrastClass(e);"string"==typeof n&&e.classList.add(n)}getContrastClass(e){const t=e.slideBackgroundElement;let i=e.getAttribute("data-background-color");if(!i||!A(i)){let e=window.getComputedStyle(t);e&&e.backgroundColor&&(i=e.backgroundColor)}if(i){const e=A(i);if(e&&0!==e.a)return"string"==typeof(s=i)&&(s=A(s)),(s?(299*s.r+587*s.g+114*s.b)/1e3:null)<128?"has-dark-background":"has-light-background"}var s;return null}bubbleSlideContrastClassToElement(e,t){["has-light-background","has-dark-background"].forEach((i=>{e.classList.contains(i)?t.classList.add(i):t.classList.remove(i)}),this)}update(e=!1){let i=this.Reveal.getCurrentSlide(),s=this.Reveal.getIndices(),a=null,n=this.Reveal.getConfig().rtl?"future":"past",r=this.Reveal.getConfig().rtl?"past":"future";if(Array.from(this.element.childNodes).forEach(((i,o)=>{i.classList.remove("past","present","future"),os.h?i.classList.add(r):(i.classList.add("present"),a=i),(e||o===s.h)&&t(i,".slide-background").forEach(((e,t)=>{e.classList.remove("past","present","future");const i="number"==typeof s.v?s.v:0;ti?e.classList.add("future"):(e.classList.add("present"),o===s.h&&(a=e))}))})),this.previousBackground&&this.Reveal.slideContent.stopEmbeddedContent(this.previousBackground,{unloadIframes:!this.Reveal.slideContent.shouldPreload(this.previousBackground)}),a){this.Reveal.slideContent.startEmbeddedContent(a);let e=a.querySelector(".slide-background-content");if(e){let t=e.style.backgroundImage||"";/\.gif/i.test(t)&&(e.style.backgroundImage="",window.getComputedStyle(e).opacity,e.style.backgroundImage=t)}let t=this.previousBackground?this.previousBackground.getAttribute("data-background-hash"):null,i=a.getAttribute("data-background-hash");i&&i===t&&a!==this.previousBackground&&this.element.classList.add("no-transition"),this.previousBackground=a}i&&this.bubbleSlideContrastClassToElement(i,this.Reveal.getRevealElement()),setTimeout((()=>{this.element.classList.remove("no-transition")}),1)}updateParallax(){let e=this.Reveal.getIndices();if(this.Reveal.getConfig().parallaxBackgroundImage){let t,i,s=this.Reveal.getHorizontalSlides(),a=this.Reveal.getVerticalSlides(),n=this.element.style.backgroundSize.split(" ");1===n.length?t=i=parseInt(n[0],10):(t=parseInt(n[0],10),i=parseInt(n[1],10));let r,o,l=this.element.offsetWidth,d=s.length;r="number"==typeof this.Reveal.getConfig().parallaxBackgroundHorizontal?this.Reveal.getConfig().parallaxBackgroundHorizontal:d>1?(t-l)/(d-1):0,o=r*e.h*-1;let c,h,u=this.element.offsetHeight,g=a.length;c="number"==typeof this.Reveal.getConfig().parallaxBackgroundVertical?this.Reveal.getConfig().parallaxBackgroundVertical:(i-u)/(g-1),h=g>0?c*e.v:0,this.element.style.backgroundPosition=o+"px "+-h+"px"}}destroy(){this.element.remove()}}let k=0;class L{constructor(e){this.Reveal=e}run(e,t){this.reset();let i=this.Reveal.getSlides(),s=i.indexOf(t),a=i.indexOf(e);if(e.hasAttribute("data-auto-animate")&&t.hasAttribute("data-auto-animate")&&e.getAttribute("data-auto-animate-id")===t.getAttribute("data-auto-animate-id")&&!(s>a?t:e).hasAttribute("data-auto-animate-restart")){this.autoAnimateStyleSheet=this.autoAnimateStyleSheet||l();let i=this.getAutoAnimateOptions(t);e.dataset.autoAnimate="pending",t.dataset.autoAnimate="pending",i.slideDirection=s>a?"forward":"backward";let n="none"===e.style.display;n&&(e.style.display=this.Reveal.getConfig().display);let r=this.getAutoAnimatableElements(e,t).map((e=>this.autoAnimateElements(e.from,e.to,e.options||{},i,k++)));if(n&&(e.style.display="none"),"false"!==t.dataset.autoAnimateUnmatched&&!0===this.Reveal.getConfig().autoAnimateUnmatched){let e=.8*i.duration,s=.2*i.duration;this.getUnmatchedAutoAnimateElements(t).forEach((e=>{let t=this.getAutoAnimateOptions(e,i),s="unmatched";t.duration===i.duration&&t.delay===i.delay||(s="unmatched-"+k++,r.push(`[data-auto-animate="running"] [data-auto-animate-target="${s}"] { transition: opacity ${t.duration}s ease ${t.delay}s; }`)),e.dataset.autoAnimateTarget=s}),this),r.push(`[data-auto-animate="running"] [data-auto-animate-target="unmatched"] { transition: opacity ${e}s ease ${s}s; }`)}this.autoAnimateStyleSheet.innerHTML=r.join(""),requestAnimationFrame((()=>{this.autoAnimateStyleSheet&&(getComputedStyle(this.autoAnimateStyleSheet).fontWeight,t.dataset.autoAnimate="running")})),this.Reveal.dispatchEvent({type:"autoanimate",data:{fromSlide:e,toSlide:t,sheet:this.autoAnimateStyleSheet}})}}reset(){t(this.Reveal.getRevealElement(),'[data-auto-animate]:not([data-auto-animate=""])').forEach((e=>{e.dataset.autoAnimate=""})),t(this.Reveal.getRevealElement(),"[data-auto-animate-target]").forEach((e=>{delete e.dataset.autoAnimateTarget})),this.autoAnimateStyleSheet&&this.autoAnimateStyleSheet.parentNode&&(this.autoAnimateStyleSheet.parentNode.removeChild(this.autoAnimateStyleSheet),this.autoAnimateStyleSheet=null)}autoAnimateElements(e,t,i,s,a){e.dataset.autoAnimateTarget="",t.dataset.autoAnimateTarget=a;let n=this.getAutoAnimateOptions(t,s);void 0!==i.delay&&(n.delay=i.delay),void 0!==i.duration&&(n.duration=i.duration),void 0!==i.easing&&(n.easing=i.easing);let r=this.getAutoAnimatableProperties("from",e,i),o=this.getAutoAnimatableProperties("to",t,i);if(t.classList.contains("fragment")&&(delete o.styles.opacity,e.classList.contains("fragment"))){(e.className.match(w)||[""])[0]===(t.className.match(w)||[""])[0]&&"forward"===s.slideDirection&&t.classList.add("visible","disabled")}if(!1!==i.translate||!1!==i.scale){let e=this.Reveal.getScale(),t={x:(r.x-o.x)/e,y:(r.y-o.y)/e,scaleX:r.width/o.width,scaleY:r.height/o.height};t.x=Math.round(1e3*t.x)/1e3,t.y=Math.round(1e3*t.y)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3,t.scaleX=Math.round(1e3*t.scaleX)/1e3;let s=!1!==i.translate&&(0!==t.x||0!==t.y),a=!1!==i.scale&&(0!==t.scaleX||0!==t.scaleY);if(s||a){let e=[];s&&e.push(`translate(${t.x}px, ${t.y}px)`),a&&e.push(`scale(${t.scaleX}, ${t.scaleY})`),r.styles.transform=e.join(" "),r.styles["transform-origin"]="top left",o.styles.transform="none"}}for(let e in o.styles){const t=o.styles[e],i=r.styles[e];t===i?delete o.styles[e]:(!0===t.explicitValue&&(o.styles[e]=t.value),!0===i.explicitValue&&(r.styles[e]=i.value))}let l="",d=Object.keys(o.styles);if(d.length>0){r.styles.transition="none",o.styles.transition=`all ${n.duration}s ${n.easing} ${n.delay}s`,o.styles["transition-property"]=d.join(", "),o.styles["will-change"]=d.join(", "),l='[data-auto-animate-target="'+a+'"] {'+Object.keys(r.styles).map((e=>e+": "+r.styles[e]+" !important;")).join("")+'}[data-auto-animate="running"] [data-auto-animate-target="'+a+'"] {'+Object.keys(o.styles).map((e=>e+": "+o.styles[e]+" !important;")).join("")+"}"}return l}getAutoAnimateOptions(t,i){let s={easing:this.Reveal.getConfig().autoAnimateEasing,duration:this.Reveal.getConfig().autoAnimateDuration,delay:0};if(s=e(s,i),t.parentNode){let e=r(t.parentNode,"[data-auto-animate-target]");e&&(s=this.getAutoAnimateOptions(e,s))}return t.dataset.autoAnimateEasing&&(s.easing=t.dataset.autoAnimateEasing),t.dataset.autoAnimateDuration&&(s.duration=parseFloat(t.dataset.autoAnimateDuration)),t.dataset.autoAnimateDelay&&(s.delay=parseFloat(t.dataset.autoAnimateDelay)),s}getAutoAnimatableProperties(e,t,i){let s=this.Reveal.getConfig(),a={styles:[]};if(!1!==i.translate||!1!==i.scale){let e;if("function"==typeof i.measure)e=i.measure(t);else if(s.center)e=t.getBoundingClientRect();else{let i=this.Reveal.getScale();e={x:t.offsetLeft*i,y:t.offsetTop*i,width:t.offsetWidth*i,height:t.offsetHeight*i}}a.x=e.x,a.y=e.y,a.width=e.width,a.height=e.height}const n=getComputedStyle(t);return(i.styles||s.autoAnimateStyles).forEach((t=>{let i;"string"==typeof t&&(t={property:t}),void 0!==t.from&&"from"===e?i={value:t.from,explicitValue:!0}:void 0!==t.to&&"to"===e?i={value:t.to,explicitValue:!0}:("line-height"===t.property&&(i=parseFloat(n["line-height"])/parseFloat(n["font-size"])),isNaN(i)&&(i=n[t.property])),""!==i&&(a.styles[t.property]=i)})),a}getAutoAnimatableElements(e,t){let i=("function"==typeof this.Reveal.getConfig().autoAnimateMatcher?this.Reveal.getConfig().autoAnimateMatcher:this.getAutoAnimatePairs).call(this,e,t),s=[];return i.filter(((e,t)=>{if(-1===s.indexOf(e.to))return s.push(e.to),!0}))}getAutoAnimatePairs(e,t){let i=[];const s="h1, h2, h3, h4, h5, h6, p, li";return this.findAutoAnimateMatches(i,e,t,"[data-id]",(e=>e.nodeName+":::"+e.getAttribute("data-id"))),this.findAutoAnimateMatches(i,e,t,s,(e=>e.nodeName+":::"+e.innerText)),this.findAutoAnimateMatches(i,e,t,"img, video, iframe",(e=>e.nodeName+":::"+(e.getAttribute("src")||e.getAttribute("data-src")))),this.findAutoAnimateMatches(i,e,t,"pre",(e=>e.nodeName+":::"+e.innerText)),i.forEach((e=>{n(e.from,s)?e.options={scale:!1}:n(e.from,"pre")&&(e.options={scale:!1,styles:["width","height"]},this.findAutoAnimateMatches(i,e.from,e.to,".hljs .hljs-ln-code",(e=>e.textContent),{scale:!1,styles:[],measure:this.getLocalBoundingBox.bind(this)}),this.findAutoAnimateMatches(i,e.from,e.to,".hljs .hljs-ln-numbers[data-line-number]",(e=>e.getAttribute("data-line-number")),{scale:!1,styles:["width"],measure:this.getLocalBoundingBox.bind(this)}))}),this),i}getLocalBoundingBox(e){const t=this.Reveal.getScale();return{x:Math.round(e.offsetLeft*t*100)/100,y:Math.round(e.offsetTop*t*100)/100,width:Math.round(e.offsetWidth*t*100)/100,height:Math.round(e.offsetHeight*t*100)/100}}findAutoAnimateMatches(e,t,i,s,a,n){let r={},o={};[].slice.call(t.querySelectorAll(s)).forEach(((e,t)=>{const i=a(e);"string"==typeof i&&i.length&&(r[i]=r[i]||[],r[i].push(e))})),[].slice.call(i.querySelectorAll(s)).forEach(((t,i)=>{const s=a(t);let l;if(o[s]=o[s]||[],o[s].push(t),r[s]){const e=o[s].length-1,t=r[s].length-1;r[s][e]?(l=r[s][e],r[s][e]=null):r[s][t]&&(l=r[s][t],r[s][t]=null)}l&&e.push({from:l,to:t,options:n})}))}getUnmatchedAutoAnimateElements(e){return[].slice.call(e.children).reduce(((e,t)=>{const i=t.querySelector("[data-auto-animate-target]");return t.hasAttribute("data-auto-animate-target")||i||e.push(t),t.querySelector("[data-auto-animate-target]")&&(e=e.concat(this.getUnmatchedAutoAnimateElements(t))),e}),[])}}class C{constructor(e){this.Reveal=e,this.active=!1,this.activatedCallbacks=[],this.onScroll=this.onScroll.bind(this)}activate(){if(this.active)return;const e=this.Reveal.getState();this.active=!0,this.slideHTMLBeforeActivation=this.Reveal.getSlidesElement().innerHTML;const i=t(this.Reveal.getRevealElement(),f),s=t(this.Reveal.getRevealElement(),".backgrounds>.slide-background");let a;this.viewportElement.classList.add("loading-scroll-mode","reveal-scroll");const n=window.getComputedStyle(this.viewportElement);n&&n.background&&(a=n.background);const r=[],o=i[0].parentNode;let l;const d=(e,t,i,n)=>{let o;if(l&&this.Reveal.shouldAutoAnimateBetween(l,e))o=document.createElement("div"),o.className="scroll-page-content scroll-auto-animate-page",o.style.display="none",l.closest(".scroll-page-content").parentNode.appendChild(o);else{const e=document.createElement("div");if(e.className="scroll-page",r.push(e),n&&s.length>t){const i=s[t],n=window.getComputedStyle(i);n&&n.background?e.style.background=n.background:a&&(e.style.background=a)}else a&&(e.style.background=a);const i=document.createElement("div");i.className="scroll-page-sticky",e.appendChild(i),o=document.createElement("div"),o.className="scroll-page-content",i.appendChild(o)}o.appendChild(e),e.classList.remove("past","future"),e.setAttribute("data-index-h",t),e.setAttribute("data-index-v",i),e.slideBackgroundElement&&(e.slideBackgroundElement.remove("past","future"),o.insertBefore(e.slideBackgroundElement,e)),l=e};i.forEach(((e,t)=>{this.Reveal.isVerticalStack(e)?e.querySelectorAll("section").forEach(((e,i)=>{d(e,t,i,!0)})):d(e,t,0)}),this),this.createProgressBar(),t(this.Reveal.getRevealElement(),".stack").forEach((e=>e.remove())),r.forEach((e=>o.appendChild(e))),this.Reveal.slideContent.layout(this.Reveal.getSlidesElement()),this.Reveal.layout(),this.Reveal.setState(e),this.activatedCallbacks.forEach((e=>e())),this.activatedCallbacks=[],this.restoreScrollPosition(),this.viewportElement.classList.remove("loading-scroll-mode"),this.viewportElement.addEventListener("scroll",this.onScroll,{passive:!0})}deactivate(){if(!this.active)return;const e=this.Reveal.getState();this.active=!1,this.viewportElement.removeEventListener("scroll",this.onScroll),this.viewportElement.classList.remove("reveal-scroll"),this.removeProgressBar(),this.Reveal.getSlidesElement().innerHTML=this.slideHTMLBeforeActivation,this.Reveal.sync(),this.Reveal.setState(e),this.slideHTMLBeforeActivation=null}toggle(e){"boolean"==typeof e?e?this.activate():this.deactivate():this.isActive()?this.deactivate():this.activate()}isActive(){return this.active}createProgressBar(){this.progressBar=document.createElement("div"),this.progressBar.className="scrollbar",this.progressBarInner=document.createElement("div"),this.progressBarInner.className="scrollbar-inner",this.progressBar.appendChild(this.progressBarInner),this.progressBarPlayhead=document.createElement("div"),this.progressBarPlayhead.className="scrollbar-playhead",this.progressBarInner.appendChild(this.progressBarPlayhead),this.viewportElement.insertBefore(this.progressBar,this.viewportElement.firstChild);const e=e=>{let t=(e.clientY-this.progressBarInner.getBoundingClientRect().top)/this.progressBarHeight;t=Math.max(Math.min(t,1),0),this.viewportElement.scrollTop=t*(this.viewportElement.scrollHeight-this.viewportElement.offsetHeight)},t=i=>{this.draggingProgressBar=!1,this.showProgressBar(),document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",t)};this.progressBarInner.addEventListener("mousedown",(i=>{i.preventDefault(),this.draggingProgressBar=!0,document.addEventListener("mousemove",e),document.addEventListener("mouseup",t),e(i)}))}removeProgressBar(){this.progressBar&&(this.progressBar.remove(),this.progressBar=null)}layout(){this.isActive()&&(this.syncPages(),this.syncScrollPosition())}syncPages(){const e=this.Reveal.getConfig(),t=this.Reveal.getComputedSlideSize(window.innerWidth,window.innerHeight),i=this.Reveal.getScale(),s="compact"===e.scrollLayout,a=this.viewportElement.offsetHeight,n=t.height*i,r=s?n:a;this.scrollTriggerHeight=s?n:a,this.viewportElement.style.setProperty("--page-height",r+"px"),this.viewportElement.style.scrollSnapType="string"==typeof e.scrollSnap?`y ${e.scrollSnap}`:"",this.slideTriggers=[];const o=Array.from(this.Reveal.getRevealElement().querySelectorAll(".scroll-page"));this.pages=o.map((i=>{const n=this.createPage({pageElement:i,slideElement:i.querySelector("section"),stickyElement:i.querySelector(".scroll-page-sticky"),contentElement:i.querySelector(".scroll-page-content"),backgroundElement:i.querySelector(".slide-background"),autoAnimateElements:i.querySelectorAll(".scroll-auto-animate-page"),autoAnimatePages:[]});n.pageElement.style.setProperty("--slide-height",!0===e.center?"auto":t.height+"px"),this.slideTriggers.push({page:n,activate:()=>this.activatePage(n),deactivate:()=>this.deactivatePage(n)}),this.createFragmentTriggersForPage(n),n.autoAnimateElements.length>0&&this.createAutoAnimateTriggersForPage(n);let o=Math.max(n.scrollTriggers.length-1,0);o+=n.autoAnimatePages.reduce(((e,t)=>e+Math.max(t.scrollTriggers.length-1,0)),n.autoAnimatePages.length),n.pageElement.querySelectorAll(".scroll-snap-point").forEach((e=>e.remove()));for(let e=0;e0?(n.pageHeight=a,n.pageElement.style.setProperty("--page-height",a+"px")):(n.pageHeight=r,n.pageElement.style.removeProperty("--page-height")),n.scrollPadding=this.scrollTriggerHeight*o,n.totalHeight=n.pageHeight+n.scrollPadding,n.pageElement.style.setProperty("--page-scroll-padding",n.scrollPadding+"px"),o>0?(n.stickyElement.style.position="sticky",n.stickyElement.style.top=Math.max((a-n.pageHeight)/2,0)+"px"):(n.stickyElement.style.position="relative",n.pageElement.style.scrollSnapAlign=n.pageHeight1?(this.progressBar||this.createProgressBar(),this.syncProgressBar()):this.removeProgressBar()}setTriggerRanges(){this.totalScrollTriggerCount=this.slideTriggers.reduce(((e,t)=>e+Math.max(t.page.scrollTriggers.length,1)),0);let e=0;this.slideTriggers.forEach(((t,i)=>{t.range=[e,e+Math.max(t.page.scrollTriggers.length,1)/this.totalScrollTriggerCount];const s=(t.range[1]-t.range[0])/t.page.scrollTriggers.length;t.page.scrollTriggers.forEach(((t,i)=>{t.range=[e+i*s,e+(i+1)*s]})),e=t.range[1]}))}createFragmentTriggersForPage(e,t){t=t||e.slideElement;const i=this.Reveal.fragments.sort(t.querySelectorAll(".fragment"),!0);return i.length&&(e.fragments=this.Reveal.fragments.sort(t.querySelectorAll(".fragment:not(.disabled)")),e.scrollTriggers.push({activate:()=>{this.Reveal.fragments.update(-1,e.fragments,t)}}),i.forEach(((i,s)=>{e.scrollTriggers.push({activate:()=>{this.Reveal.fragments.update(s,e.fragments,t)}})}))),e.scrollTriggers.length}createAutoAnimateTriggersForPage(e){e.autoAnimateElements.length>0&&this.slideTriggers.push(...Array.from(e.autoAnimateElements).map(((t,i)=>{let s=this.createPage({slideElement:t.querySelector("section"),contentElement:t,backgroundElement:t.querySelector(".slide-background")});return this.createFragmentTriggersForPage(s,s.slideElement),e.autoAnimatePages.push(s),{page:s,activate:()=>this.activatePage(s),deactivate:()=>this.deactivatePage(s)}})))}createPage(e){return e.scrollTriggers=[],e.indexh=parseInt(e.slideElement.getAttribute("data-index-h"),10),e.indexv=parseInt(e.slideElement.getAttribute("data-index-v"),10),e}syncProgressBar(){this.progressBarInner.querySelectorAll(".scrollbar-slide").forEach((e=>e.remove()));const e=this.viewportElement.scrollHeight,t=this.viewportElement.offsetHeight,i=t/e;this.progressBarHeight=this.progressBarInner.offsetHeight,this.playheadHeight=Math.max(i*this.progressBarHeight,8),this.progressBarScrollableHeight=this.progressBarHeight-this.playheadHeight;const s=t/e*this.progressBarHeight,a=Math.min(s/8,4);this.progressBarPlayhead.style.height=this.playheadHeight-a+"px",s>6?this.slideTriggers.forEach((e=>{const{page:t}=e;t.progressBarSlide=document.createElement("div"),t.progressBarSlide.className="scrollbar-slide",t.progressBarSlide.style.top=e.range[0]*this.progressBarHeight+"px",t.progressBarSlide.style.height=(e.range[1]-e.range[0])*this.progressBarHeight-a+"px",t.progressBarSlide.classList.toggle("has-triggers",t.scrollTriggers.length>0),this.progressBarInner.appendChild(t.progressBarSlide),t.scrollTriggerElements=t.scrollTriggers.map(((i,s)=>{const n=document.createElement("div");return n.className="scrollbar-trigger",n.style.top=(i.range[0]-e.range[0])*this.progressBarHeight+"px",n.style.height=(i.range[1]-i.range[0])*this.progressBarHeight-a+"px",t.progressBarSlide.appendChild(n),0===s&&(n.style.display="none"),n}))})):this.pages.forEach((e=>e.progressBarSlide=null))}syncScrollPosition(){const e=this.viewportElement.offsetHeight,t=e/this.viewportElement.scrollHeight,i=this.viewportElement.scrollTop,s=this.viewportElement.scrollHeight-e,a=Math.max(Math.min(i/s,1),0),n=Math.max(Math.min((i+e/2)/this.viewportElement.scrollHeight,1),0);let r;this.slideTriggers.forEach((e=>{const{page:i}=e;a>=e.range[0]-2*t&&a<=e.range[1]+2*t&&!i.loaded?(i.loaded=!0,this.Reveal.slideContent.load(i.slideElement)):i.loaded&&(i.loaded=!1,this.Reveal.slideContent.unload(i.slideElement)),a>=e.range[0]&&a<=e.range[1]?(this.activateTrigger(e),r=e.page):e.active&&this.deactivateTrigger(e)})),r&&r.scrollTriggers.forEach((e=>{n>=e.range[0]&&n<=e.range[1]?this.activateTrigger(e):e.active&&this.deactivateTrigger(e)})),this.setProgressBarValue(i/(this.viewportElement.scrollHeight-e))}setProgressBarValue(e){this.progressBar&&(this.progressBarPlayhead.style.transform=`translateY(${e*this.progressBarScrollableHeight}px)`,this.getAllPages().filter((e=>e.progressBarSlide)).forEach((e=>{e.progressBarSlide.classList.toggle("active",!0===e.active),e.scrollTriggers.forEach(((t,i)=>{e.scrollTriggerElements[i].classList.toggle("active",!0===e.active&&!0===t.active)}))})),this.showProgressBar())}showProgressBar(){this.progressBar.classList.add("visible"),clearTimeout(this.hideProgressBarTimeout),"auto"!==this.Reveal.getConfig().scrollProgress||this.draggingProgressBar||(this.hideProgressBarTimeout=setTimeout((()=>{this.progressBar&&this.progressBar.classList.remove("visible")}),500))}prev(){this.viewportElement.scrollTop-=this.scrollTriggerHeight}next(){this.viewportElement.scrollTop+=this.scrollTriggerHeight}scrollToSlide(e){if(this.active){const t=this.getScrollTriggerBySlide(e);t&&(this.viewportElement.scrollTop=t.range[0]*(this.viewportElement.scrollHeight-this.viewportElement.offsetHeight))}else this.activatedCallbacks.push((()=>this.scrollToSlide(e)))}storeScrollPosition(){clearTimeout(this.storeScrollPositionTimeout),this.storeScrollPositionTimeout=setTimeout((()=>{sessionStorage.setItem("reveal-scroll-top",this.viewportElement.scrollTop),sessionStorage.setItem("reveal-scroll-origin",location.origin+location.pathname),this.storeScrollPositionTimeout=null}),50)}restoreScrollPosition(){const e=sessionStorage.getItem("reveal-scroll-top"),t=sessionStorage.getItem("reveal-scroll-origin");e&&t===location.origin+location.pathname&&(this.viewportElement.scrollTop=parseInt(e,10))}activatePage(e){if(!e.active){e.active=!0;const{slideElement:t,backgroundElement:i,contentElement:s,indexh:a,indexv:n}=e;s.style.display="block",t.classList.add("present"),i&&i.classList.add("present"),this.Reveal.setCurrentScrollPage(t,a,n),this.Reveal.backgrounds.bubbleSlideContrastClassToElement(t,this.viewportElement),Array.from(s.parentNode.querySelectorAll(".scroll-page-content")).forEach((e=>{e!==s&&(e.style.display="none")}))}}deactivatePage(e){e.active&&(e.active=!1,e.slideElement&&e.slideElement.classList.remove("present"),e.backgroundElement&&e.backgroundElement.classList.remove("present"))}activateTrigger(e){e.active||(e.active=!0,e.activate())}deactivateTrigger(e){e.active&&(e.active=!1,e.deactivate&&e.deactivate())}getSlideByIndices(e,t){const i=this.getAllPages().find((i=>i.indexh===e&&i.indexv===t));return i?i.slideElement:null}getScrollTriggerBySlide(e){return this.slideTriggers.find((t=>t.page.slideElement===e))}getAllPages(){return this.pages.flatMap((e=>[e,...e.autoAnimatePages||[]]))}onScroll(){this.syncScrollPosition(),this.storeScrollPosition()}get viewportElement(){return this.Reveal.getViewportElement()}}class x{constructor(e){this.Reveal=e}async activate(){const e=this.Reveal.getConfig(),i=t(this.Reveal.getRevealElement(),m),s=e.slideNumber&&/all|print/i.test(e.showSlideNumber),a=this.Reveal.getComputedSlideSize(window.innerWidth,window.innerHeight),n=Math.floor(a.width*(1+e.margin)),r=Math.floor(a.height*(1+e.margin)),o=a.width,d=a.height;await new Promise(requestAnimationFrame),l("@page{size:"+n+"px "+r+"px; margin: 0px;}"),l(".reveal section>img, .reveal section>video, .reveal section>iframe{max-width: "+o+"px; max-height:"+d+"px}"),document.documentElement.classList.add("reveal-print","print-pdf"),document.body.style.width=n+"px",document.body.style.height=r+"px";const c=this.Reveal.getViewportElement();let h;if(c){const e=window.getComputedStyle(c);e&&e.background&&(h=e.background)}await new Promise(requestAnimationFrame),this.Reveal.layoutSlideContents(o,d),await new Promise(requestAnimationFrame);const u=i.map((e=>e.scrollHeight)),g=[],p=i[0].parentNode;let v=1;i.forEach((function(i,a){if(!1===i.classList.contains("stack")){let l=(n-o)/2,c=(r-d)/2;const p=u[a];let m=Math.max(Math.ceil(p/r),1);m=Math.min(m,e.pdfMaxPagesPerSlide),(1===m&&e.center||i.classList.contains("center"))&&(c=Math.max((r-p)/2,0));const f=document.createElement("div");if(g.push(f),f.className="pdf-page",f.style.height=(r+e.pdfPageHeightOffset)*m+"px",h&&(f.style.background=h),f.appendChild(i),i.style.left=l+"px",i.style.top=c+"px",i.style.width=o+"px",this.Reveal.slideContent.layout(i),i.slideBackgroundElement&&f.insertBefore(i.slideBackgroundElement,i),e.showNotes){const t=this.Reveal.getSlideNotes(i);if(t){const i=8,s="string"==typeof e.showNotes?e.showNotes:"inline",a=document.createElement("div");a.classList.add("speaker-notes"),a.classList.add("speaker-notes-pdf"),a.setAttribute("data-layout",s),a.innerHTML=t,"separate-page"===s?g.push(a):(a.style.left=i+"px",a.style.bottom=i+"px",a.style.width=n-2*i+"px",f.appendChild(a))}}if(s){const e=document.createElement("div");e.classList.add("slide-number"),e.classList.add("slide-number-pdf"),e.innerHTML=v++,f.appendChild(e)}if(e.pdfSeparateFragments){const e=this.Reveal.fragments.sort(f.querySelectorAll(".fragment"),!0);let t;e.forEach((function(e,i){t&&t.forEach((function(e){e.classList.remove("current-fragment")})),e.forEach((function(e){e.classList.add("visible","current-fragment")}),this);const a=f.cloneNode(!0);if(s){const e=i+1;a.querySelector(".slide-number-pdf").innerHTML+="."+e}g.push(a),t=e}),this),e.forEach((function(e){e.forEach((function(e){e.classList.remove("visible","current-fragment")}))}))}else t(f,".fragment:not(.fade-out)").forEach((function(e){e.classList.add("visible")}))}}),this),await new Promise(requestAnimationFrame),g.forEach((e=>p.appendChild(e))),this.Reveal.slideContent.layout(this.Reveal.getSlidesElement()),this.Reveal.dispatchEvent({type:"pdf-ready"}),c.classList.remove("loading-scroll-mode")}isActive(){return"print"===this.Reveal.getConfig().view}}class P{constructor(e){this.Reveal=e}configure(e,t){!1===e.fragments?this.disable():!1===t.fragments&&this.enable()}disable(){t(this.Reveal.getSlidesElement(),".fragment").forEach((e=>{e.classList.add("visible"),e.classList.remove("current-fragment")}))}enable(){t(this.Reveal.getSlidesElement(),".fragment").forEach((e=>{e.classList.remove("visible"),e.classList.remove("current-fragment")}))}availableRoutes(){let e=this.Reveal.getCurrentSlide();if(e&&this.Reveal.getConfig().fragments){let t=e.querySelectorAll(".fragment:not(.disabled)"),i=e.querySelectorAll(".fragment:not(.disabled):not(.visible)");return{prev:t.length-i.length>0,next:!!i.length}}return{prev:!1,next:!1}}sort(e,t=!1){e=Array.from(e);let i=[],s=[],a=[];e.forEach((e=>{if(e.hasAttribute("data-fragment-index")){let t=parseInt(e.getAttribute("data-fragment-index"),10);i[t]||(i[t]=[]),i[t].push(e)}else s.push([e])})),i=i.concat(s);let n=0;return i.forEach((e=>{e.forEach((e=>{a.push(e),e.setAttribute("data-fragment-index",n)})),n++})),!0===t?i:a}sortAll(){this.Reveal.getHorizontalSlides().forEach((e=>{let i=t(e,"section");i.forEach(((e,t)=>{this.sort(e.querySelectorAll(".fragment"))}),this),0===i.length&&this.sort(e.querySelectorAll(".fragment"))}))}update(e,t,i=this.Reveal.getCurrentSlide()){let s={shown:[],hidden:[]};if(i&&this.Reveal.getConfig().fragments&&(t=t||this.sort(i.querySelectorAll(".fragment"))).length){let a=0;if("number"!=typeof e){let t=this.sort(i.querySelectorAll(".fragment.visible")).pop();t&&(e=parseInt(t.getAttribute("data-fragment-index")||0,10))}Array.from(t).forEach(((t,i)=>{if(t.hasAttribute("data-fragment-index")&&(i=parseInt(t.getAttribute("data-fragment-index"),10)),a=Math.max(a,i),i<=e){let a=t.classList.contains("visible");t.classList.add("visible"),t.classList.remove("current-fragment"),i===e&&(this.Reveal.announceStatus(this.Reveal.getStatusText(t)),t.classList.add("current-fragment"),this.Reveal.slideContent.startEmbeddedContent(t)),a||(s.shown.push(t),this.Reveal.dispatchEvent({target:t,type:"visible",bubbles:!1}))}else{let e=t.classList.contains("visible");t.classList.remove("visible"),t.classList.remove("current-fragment"),e&&(this.Reveal.slideContent.stopEmbeddedContent(t),s.hidden.push(t),this.Reveal.dispatchEvent({target:t,type:"hidden",bubbles:!1}))}})),e="number"==typeof e?e:-1,e=Math.max(Math.min(e,a),-1),i.setAttribute("data-fragment",e)}return s.hidden.length&&this.Reveal.dispatchEvent({type:"fragmenthidden",data:{fragment:s.hidden[0],fragments:s.hidden}}),s.shown.length&&this.Reveal.dispatchEvent({type:"fragmentshown",data:{fragment:s.shown[0],fragments:s.shown}}),s}sync(e=this.Reveal.getCurrentSlide()){return this.sort(e.querySelectorAll(".fragment"))}goto(e,t=0){let i=this.Reveal.getCurrentSlide();if(i&&this.Reveal.getConfig().fragments){let s=this.sort(i.querySelectorAll(".fragment:not(.disabled)"));if(s.length){if("number"!=typeof e){let t=this.sort(i.querySelectorAll(".fragment:not(.disabled).visible")).pop();e=t?parseInt(t.getAttribute("data-fragment-index")||0,10):-1}e+=t;let a=this.update(e,s);return this.Reveal.controls.update(),this.Reveal.progress.update(),this.Reveal.getConfig().fragmentInURL&&this.Reveal.location.writeURL(),!(!a.shown.length&&!a.hidden.length)}}return!1}next(){return this.goto(null,1)}prev(){return this.goto(null,-1)}}class T{constructor(e){this.Reveal=e,this.active=!1,this.onSlideClicked=this.onSlideClicked.bind(this)}activate(){if(this.Reveal.getConfig().overview&&!this.Reveal.isScrollView()&&!this.isActive()){this.active=!0,this.Reveal.getRevealElement().classList.add("overview"),this.Reveal.cancelAutoSlide(),this.Reveal.getSlidesElement().appendChild(this.Reveal.getBackgroundsElement()),t(this.Reveal.getRevealElement(),m).forEach((e=>{e.classList.contains("stack")||e.addEventListener("click",this.onSlideClicked,!0)}));const e=70,i=this.Reveal.getComputedSlideSize();this.overviewSlideWidth=i.width+e,this.overviewSlideHeight=i.height+e,this.Reveal.getConfig().rtl&&(this.overviewSlideWidth=-this.overviewSlideWidth),this.Reveal.updateSlidesVisibility(),this.layout(),this.update(),this.Reveal.layout();const s=this.Reveal.getIndices();this.Reveal.dispatchEvent({type:"overviewshown",data:{indexh:s.h,indexv:s.v,currentSlide:this.Reveal.getCurrentSlide()}})}}layout(){this.Reveal.getHorizontalSlides().forEach(((e,i)=>{e.setAttribute("data-index-h",i),a(e,"translate3d("+i*this.overviewSlideWidth+"px, 0, 0)"),e.classList.contains("stack")&&t(e,"section").forEach(((e,t)=>{e.setAttribute("data-index-h",i),e.setAttribute("data-index-v",t),a(e,"translate3d(0, "+t*this.overviewSlideHeight+"px, 0)")}))})),Array.from(this.Reveal.getBackgroundsElement().childNodes).forEach(((e,i)=>{a(e,"translate3d("+i*this.overviewSlideWidth+"px, 0, 0)"),t(e,".slide-background").forEach(((e,t)=>{a(e,"translate3d(0, "+t*this.overviewSlideHeight+"px, 0)")}))}))}update(){const e=Math.min(window.innerWidth,window.innerHeight),t=Math.max(e/5,150)/e,i=this.Reveal.getIndices();this.Reveal.transformSlides({overview:["scale("+t+")","translateX("+-i.h*this.overviewSlideWidth+"px)","translateY("+-i.v*this.overviewSlideHeight+"px)"].join(" ")})}deactivate(){if(this.Reveal.getConfig().overview){this.active=!1,this.Reveal.getRevealElement().classList.remove("overview"),this.Reveal.getRevealElement().classList.add("overview-deactivating"),setTimeout((()=>{this.Reveal.getRevealElement().classList.remove("overview-deactivating")}),1),this.Reveal.getRevealElement().appendChild(this.Reveal.getBackgroundsElement()),t(this.Reveal.getRevealElement(),m).forEach((e=>{a(e,""),e.removeEventListener("click",this.onSlideClicked,!0)})),t(this.Reveal.getBackgroundsElement(),".slide-background").forEach((e=>{a(e,"")})),this.Reveal.transformSlides({overview:""});const e=this.Reveal.getIndices();this.Reveal.slide(e.h,e.v),this.Reveal.layout(),this.Reveal.cueAutoSlide(),this.Reveal.dispatchEvent({type:"overviewhidden",data:{indexh:e.h,indexv:e.v,currentSlide:this.Reveal.getCurrentSlide()}})}}toggle(e){"boolean"==typeof e?e?this.activate():this.deactivate():this.isActive()?this.deactivate():this.activate()}isActive(){return this.active}onSlideClicked(e){if(this.isActive()){e.preventDefault();let t=e.target;for(;t&&!t.nodeName.match(/section/gi);)t=t.parentNode;if(t&&!t.classList.contains("disabled")&&(this.deactivate(),t.nodeName.match(/section/gi))){let e=parseInt(t.getAttribute("data-index-h"),10),i=parseInt(t.getAttribute("data-index-v"),10);this.Reveal.slide(e,i)}}}}class N{constructor(e){this.Reveal=e,this.shortcuts={},this.bindings={},this.onDocumentKeyDown=this.onDocumentKeyDown.bind(this)}configure(e,t){"linear"===e.navigationMode?(this.shortcuts["→ , ↓ , SPACE , N , L , J"]="Next slide",this.shortcuts["← , ↑ , P , H , K"]="Previous slide"):(this.shortcuts["N , SPACE"]="Next slide",this.shortcuts["P , Shift SPACE"]="Previous slide",this.shortcuts["← , H"]="Navigate left",this.shortcuts["→ , L"]="Navigate right",this.shortcuts["↑ , K"]="Navigate up",this.shortcuts["↓ , J"]="Navigate down"),this.shortcuts["Alt + ←/↑/→/↓"]="Navigate without fragments",this.shortcuts["Shift + ←/↑/→/↓"]="Jump to first/last slide",this.shortcuts["B , ."]="Pause",this.shortcuts.F="Fullscreen",this.shortcuts.G="Jump to slide",this.shortcuts["ESC, O"]="Slide overview"}bind(){document.addEventListener("keydown",this.onDocumentKeyDown,!1)}unbind(){document.removeEventListener("keydown",this.onDocumentKeyDown,!1)}addKeyBinding(e,t){"object"==typeof e&&e.keyCode?this.bindings[e.keyCode]={callback:t,key:e.key,description:e.description}:this.bindings[e]={callback:t,key:null,description:null}}removeKeyBinding(e){delete this.bindings[e]}triggerKey(e){this.onDocumentKeyDown({keyCode:e})}registerKeyboardShortcut(e,t){this.shortcuts[e]=t}getShortcuts(){return this.shortcuts}getBindings(){return this.bindings}onDocumentKeyDown(e){let t=this.Reveal.getConfig();if("function"==typeof t.keyboardCondition&&!1===t.keyboardCondition(e))return!0;if("focused"===t.keyboardCondition&&!this.Reveal.isFocused())return!0;let i=e.keyCode,s=!this.Reveal.isAutoSliding();this.Reveal.onUserInput(e);let a=document.activeElement&&!0===document.activeElement.isContentEditable,n=document.activeElement&&document.activeElement.tagName&&/input|textarea/i.test(document.activeElement.tagName),r=document.activeElement&&document.activeElement.className&&/speaker-notes/i.test(document.activeElement.className),l=!(-1!==[32,37,38,39,40,78,80,191].indexOf(e.keyCode)&&e.shiftKey||e.altKey)&&(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey);if(a||n||r||l)return;let d,c=[66,86,190,191,112];if("object"==typeof t.keyboard)for(d in t.keyboard)"togglePause"===t.keyboard[d]&&c.push(parseInt(d,10));if(this.Reveal.isPaused()&&-1===c.indexOf(i))return!1;let h="linear"===t.navigationMode||!this.Reveal.hasHorizontalSlides()||!this.Reveal.hasVerticalSlides(),u=!1;if("object"==typeof t.keyboard)for(d in t.keyboard)if(parseInt(d,10)===i){let i=t.keyboard[d];"function"==typeof i?i.apply(null,[e]):"string"==typeof i&&"function"==typeof this.Reveal[i]&&this.Reveal[i].call(),u=!0}if(!1===u)for(d in this.bindings)if(parseInt(d,10)===i){let t=this.bindings[d].callback;"function"==typeof t?t.apply(null,[e]):"string"==typeof t&&"function"==typeof this.Reveal[t]&&this.Reveal[t].call(),u=!0}!1===u&&(u=!0,80===i||33===i?this.Reveal.prev({skipFragments:e.altKey}):78===i||34===i?this.Reveal.next({skipFragments:e.altKey}):72===i||37===i?e.shiftKey?this.Reveal.slide(0):!this.Reveal.overview.isActive()&&h?this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.left({skipFragments:e.altKey}):76===i||39===i?e.shiftKey?this.Reveal.slide(this.Reveal.getHorizontalSlides().length-1):!this.Reveal.overview.isActive()&&h?this.Reveal.next({skipFragments:e.altKey}):this.Reveal.right({skipFragments:e.altKey}):75===i||38===i?e.shiftKey?this.Reveal.slide(void 0,0):!this.Reveal.overview.isActive()&&h?this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.up({skipFragments:e.altKey}):74===i||40===i?e.shiftKey?this.Reveal.slide(void 0,Number.MAX_VALUE):!this.Reveal.overview.isActive()&&h?this.Reveal.next({skipFragments:e.altKey}):this.Reveal.down({skipFragments:e.altKey}):36===i?this.Reveal.slide(0):35===i?this.Reveal.slide(this.Reveal.getHorizontalSlides().length-1):32===i?(this.Reveal.overview.isActive()&&this.Reveal.overview.deactivate(),e.shiftKey?this.Reveal.prev({skipFragments:e.altKey}):this.Reveal.next({skipFragments:e.altKey})):[58,59,66,86,190].includes(i)||191===i&&!e.shiftKey?this.Reveal.togglePause():70===i?o(t.embedded?this.Reveal.getViewportElement():document.documentElement):65===i?t.autoSlideStoppable&&this.Reveal.toggleAutoSlide(s):71===i?t.jumpToSlide&&this.Reveal.toggleJumpToSlide():191===i&&e.shiftKey||112===i?this.Reveal.toggleHelp():u=!1),u?e.preventDefault&&e.preventDefault():27!==i&&79!==i||(!1===this.Reveal.closeOverlay()&&this.Reveal.overview.toggle(),e.preventDefault&&e.preventDefault()),this.Reveal.cueAutoSlide()}}class M{MAX_REPLACE_STATE_FREQUENCY=1e3;constructor(e){this.Reveal=e,this.writeURLTimeout=0,this.replaceStateTimestamp=0,this.onWindowHashChange=this.onWindowHashChange.bind(this)}bind(){window.addEventListener("hashchange",this.onWindowHashChange,!1)}unbind(){window.removeEventListener("hashchange",this.onWindowHashChange,!1)}getIndicesFromHash(e=window.location.hash,t={}){let i=e.replace(/^#\/?/,""),s=i.split("/");if(/^[0-9]*$/.test(s[0])||!i.length){const e=this.Reveal.getConfig();let i,a=e.hashOneBasedIndex||t.oneBasedIndex?1:0,n=parseInt(s[0],10)-a||0,r=parseInt(s[1],10)-a||0;return e.fragmentInURL&&(i=parseInt(s[2],10),isNaN(i)&&(i=void 0)),{h:n,v:r,f:i}}{let e,t;/\/[-\d]+$/g.test(i)&&(t=parseInt(i.split("/").pop(),10),t=isNaN(t)?void 0:t,i=i.split("/").shift());try{e=document.getElementById(decodeURIComponent(i)).closest(".slides section")}catch(e){}if(e)return{...this.Reveal.getIndices(e),f:t}}return null}readURL(){const e=this.Reveal.getIndices(),t=this.getIndicesFromHash();t?t.h===e.h&&t.v===e.v&&void 0===t.f||this.Reveal.slide(t.h,t.v,t.f):this.Reveal.slide(e.h||0,e.v||0)}writeURL(e){let t=this.Reveal.getConfig(),i=this.Reveal.getCurrentSlide();if(clearTimeout(this.writeURLTimeout),"number"==typeof e)this.writeURLTimeout=setTimeout(this.writeURL,e);else if(i){let e=this.getHash();t.history?window.location.hash=e:t.hash&&("/"===e?this.debouncedReplaceState(window.location.pathname+window.location.search):this.debouncedReplaceState("#"+e))}}replaceState(e){window.history.replaceState(null,null,e),this.replaceStateTimestamp=Date.now()}debouncedReplaceState(e){clearTimeout(this.replaceStateTimeout),Date.now()-this.replaceStateTimestamp>this.MAX_REPLACE_STATE_FREQUENCY?this.replaceState(e):this.replaceStateTimeout=setTimeout((()=>this.replaceState(e)),this.MAX_REPLACE_STATE_FREQUENCY)}getHash(e){let t="/",i=e||this.Reveal.getCurrentSlide(),s=i?i.getAttribute("id"):null;s&&(s=encodeURIComponent(s));let a=this.Reveal.getIndices(e);if(this.Reveal.getConfig().fragmentInURL||(a.f=void 0),"string"==typeof s&&s.length)t="/"+s,a.f>=0&&(t+="/"+a.f);else{let e=this.Reveal.getConfig().hashOneBasedIndex?1:0;(a.h>0||a.v>0||a.f>=0)&&(t+=a.h+e),(a.v>0||a.f>=0)&&(t+="/"+(a.v+e)),a.f>=0&&(t+="/"+a.f)}return t}onWindowHashChange(e){this.readURL()}}class I{constructor(e){this.Reveal=e,this.onNavigateLeftClicked=this.onNavigateLeftClicked.bind(this),this.onNavigateRightClicked=this.onNavigateRightClicked.bind(this),this.onNavigateUpClicked=this.onNavigateUpClicked.bind(this),this.onNavigateDownClicked=this.onNavigateDownClicked.bind(this),this.onNavigatePrevClicked=this.onNavigatePrevClicked.bind(this),this.onNavigateNextClicked=this.onNavigateNextClicked.bind(this),this.onEnterFullscreen=this.onEnterFullscreen.bind(this)}render(){const e=this.Reveal.getConfig().rtl,i=this.Reveal.getRevealElement();this.element=document.createElement("aside"),this.element.className="controls",this.element.innerHTML=`\n\t\t\t\n\t\t\t\n\t\t\t`,this.Reveal.getRevealElement().appendChild(this.element),this.controlsLeft=t(i,".navigate-left"),this.controlsRight=t(i,".navigate-right"),this.controlsUp=t(i,".navigate-up"),this.controlsDown=t(i,".navigate-down"),this.controlsPrev=t(i,".navigate-prev"),this.controlsNext=t(i,".navigate-next"),this.controlsFullscreen=t(i,".enter-fullscreen"),this.controlsRightArrow=this.element.querySelector(".navigate-right"),this.controlsLeftArrow=this.element.querySelector(".navigate-left"),this.controlsDownArrow=this.element.querySelector(".navigate-down")}configure(e,t){this.element.style.display=e.controls?"block":"none",this.element.setAttribute("data-controls-layout",e.controlsLayout),this.element.setAttribute("data-controls-back-arrows",e.controlsBackArrows)}bind(){let e=["touchstart","click"];g&&(e=["touchstart"]),e.forEach((e=>{this.controlsLeft.forEach((t=>t.addEventListener(e,this.onNavigateLeftClicked,!1))),this.controlsRight.forEach((t=>t.addEventListener(e,this.onNavigateRightClicked,!1))),this.controlsUp.forEach((t=>t.addEventListener(e,this.onNavigateUpClicked,!1))),this.controlsDown.forEach((t=>t.addEventListener(e,this.onNavigateDownClicked,!1))),this.controlsPrev.forEach((t=>t.addEventListener(e,this.onNavigatePrevClicked,!1))),this.controlsNext.forEach((t=>t.addEventListener(e,this.onNavigateNextClicked,!1))),this.controlsFullscreen.forEach((t=>t.addEventListener(e,this.onEnterFullscreen,!1)))}))}unbind(){["touchstart","click"].forEach((e=>{this.controlsLeft.forEach((t=>t.removeEventListener(e,this.onNavigateLeftClicked,!1))),this.controlsRight.forEach((t=>t.removeEventListener(e,this.onNavigateRightClicked,!1))),this.controlsUp.forEach((t=>t.removeEventListener(e,this.onNavigateUpClicked,!1))),this.controlsDown.forEach((t=>t.removeEventListener(e,this.onNavigateDownClicked,!1))),this.controlsPrev.forEach((t=>t.removeEventListener(e,this.onNavigatePrevClicked,!1))),this.controlsNext.forEach((t=>t.removeEventListener(e,this.onNavigateNextClicked,!1))),this.controlsFullscreen.forEach((t=>t.removeEventListener(e,this.onEnterFullscreen,!1)))}))}update(){let e=this.Reveal.availableRoutes();[...this.controlsLeft,...this.controlsRight,...this.controlsUp,...this.controlsDown,...this.controlsPrev,...this.controlsNext].forEach((e=>{e.classList.remove("enabled","fragmented"),e.setAttribute("disabled","disabled")})),e.left&&this.controlsLeft.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),e.right&&this.controlsRight.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),e.up&&this.controlsUp.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),e.down&&this.controlsDown.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),(e.left||e.up)&&this.controlsPrev.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")})),(e.right||e.down)&&this.controlsNext.forEach((e=>{e.classList.add("enabled"),e.removeAttribute("disabled")}));let t=this.Reveal.getCurrentSlide();if(t){let e=this.Reveal.fragments.availableRoutes();e.prev&&this.controlsPrev.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),e.next&&this.controlsNext.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),this.Reveal.isVerticalSlide(t)?(e.prev&&this.controlsUp.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),e.next&&this.controlsDown.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")}))):(e.prev&&this.controlsLeft.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})),e.next&&this.controlsRight.forEach((e=>{e.classList.add("fragmented","enabled"),e.removeAttribute("disabled")})))}if(this.Reveal.getConfig().controlsTutorial){let t=this.Reveal.getIndices();!this.Reveal.hasNavigatedVertically()&&e.down?this.controlsDownArrow.classList.add("highlight"):(this.controlsDownArrow.classList.remove("highlight"),this.Reveal.getConfig().rtl?!this.Reveal.hasNavigatedHorizontally()&&e.left&&0===t.v?this.controlsLeftArrow.classList.add("highlight"):this.controlsLeftArrow.classList.remove("highlight"):!this.Reveal.hasNavigatedHorizontally()&&e.right&&0===t.v?this.controlsRightArrow.classList.add("highlight"):this.controlsRightArrow.classList.remove("highlight"))}}destroy(){this.unbind(),this.element.remove()}onNavigateLeftClicked(e){e.preventDefault(),this.Reveal.onUserInput(),"linear"===this.Reveal.getConfig().navigationMode?this.Reveal.prev():this.Reveal.left()}onNavigateRightClicked(e){e.preventDefault(),this.Reveal.onUserInput(),"linear"===this.Reveal.getConfig().navigationMode?this.Reveal.next():this.Reveal.right()}onNavigateUpClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.up()}onNavigateDownClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.down()}onNavigatePrevClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.prev()}onNavigateNextClicked(e){e.preventDefault(),this.Reveal.onUserInput(),this.Reveal.next()}onEnterFullscreen(e){const t=this.Reveal.getConfig(),i=this.Reveal.getViewportElement();o(t.embedded?i:i.parentElement)}}class B{constructor(e){this.Reveal=e,this.onProgressClicked=this.onProgressClicked.bind(this)}render(){this.element=document.createElement("div"),this.element.className="progress",this.Reveal.getRevealElement().appendChild(this.element),this.bar=document.createElement("span"),this.element.appendChild(this.bar)}configure(e,t){this.element.style.display=e.progress?"block":"none"}bind(){this.Reveal.getConfig().progress&&this.element&&this.element.addEventListener("click",this.onProgressClicked,!1)}unbind(){this.Reveal.getConfig().progress&&this.element&&this.element.removeEventListener("click",this.onProgressClicked,!1)}update(){if(this.Reveal.getConfig().progress&&this.bar){let e=this.Reveal.getProgress();this.Reveal.getTotalSlides()<2&&(e=0),this.bar.style.transform="scaleX("+e+")"}}getMaxWidth(){return this.Reveal.getRevealElement().offsetWidth}onProgressClicked(e){this.Reveal.onUserInput(e),e.preventDefault();let t=this.Reveal.getSlides(),i=t.length,s=Math.floor(e.clientX/this.getMaxWidth()*i);this.Reveal.getConfig().rtl&&(s=i-s);let a=this.Reveal.getIndices(t[s]);this.Reveal.slide(a.h,a.v)}destroy(){this.element.remove()}}class H{constructor(e){this.Reveal=e,this.lastMouseWheelStep=0,this.cursorHidden=!1,this.cursorInactiveTimeout=0,this.onDocumentCursorActive=this.onDocumentCursorActive.bind(this),this.onDocumentMouseScroll=this.onDocumentMouseScroll.bind(this)}configure(e,t){e.mouseWheel?document.addEventListener("wheel",this.onDocumentMouseScroll,!1):document.removeEventListener("wheel",this.onDocumentMouseScroll,!1),e.hideInactiveCursor?(document.addEventListener("mousemove",this.onDocumentCursorActive,!1),document.addEventListener("mousedown",this.onDocumentCursorActive,!1)):(this.showCursor(),document.removeEventListener("mousemove",this.onDocumentCursorActive,!1),document.removeEventListener("mousedown",this.onDocumentCursorActive,!1))}showCursor(){this.cursorHidden&&(this.cursorHidden=!1,this.Reveal.getRevealElement().style.cursor="")}hideCursor(){!1===this.cursorHidden&&(this.cursorHidden=!0,this.Reveal.getRevealElement().style.cursor="none")}destroy(){this.showCursor(),document.removeEventListener("wheel",this.onDocumentMouseScroll,!1),document.removeEventListener("mousemove",this.onDocumentCursorActive,!1),document.removeEventListener("mousedown",this.onDocumentCursorActive,!1)}onDocumentCursorActive(e){this.showCursor(),clearTimeout(this.cursorInactiveTimeout),this.cursorInactiveTimeout=setTimeout(this.hideCursor.bind(this),this.Reveal.getConfig().hideCursorTime)}onDocumentMouseScroll(e){if(Date.now()-this.lastMouseWheelStep>1e3){this.lastMouseWheelStep=Date.now();let t=e.detail||-e.wheelDelta;t>0?this.Reveal.next():t<0&&this.Reveal.prev()}}}const D=(e,t)=>{const i=document.createElement("script");i.type="text/javascript",i.async=!1,i.defer=!1,i.src=e,"function"==typeof t&&(i.onload=i.onreadystatechange=e=>{("load"===e.type||/loaded|complete/.test(i.readyState))&&(i.onload=i.onreadystatechange=i.onerror=null,t())},i.onerror=e=>{i.onload=i.onreadystatechange=i.onerror=null,t(new Error("Failed loading script: "+i.src+"\n"+e))});const s=document.querySelector("head");s.insertBefore(i,s.lastChild)};class F{constructor(e){this.Reveal=e,this.state="idle",this.registeredPlugins={},this.asyncDependencies=[]}load(e,t){return this.state="loading",e.forEach(this.registerPlugin.bind(this)),new Promise((e=>{let i=[],s=0;if(t.forEach((e=>{e.condition&&!e.condition()||(e.async?this.asyncDependencies.push(e):i.push(e))})),i.length){s=i.length;const t=t=>{t&&"function"==typeof t.callback&&t.callback(),0==--s&&this.initPlugins().then(e)};i.forEach((e=>{"string"==typeof e.id?(this.registerPlugin(e),t(e)):"string"==typeof e.src?D(e.src,(()=>t(e))):(console.warn("Unrecognized plugin format",e),t())}))}else this.initPlugins().then(e)}))}initPlugins(){return new Promise((e=>{let t=Object.values(this.registeredPlugins),i=t.length;if(0===i)this.loadAsync().then(e);else{let s,a=()=>{0==--i?this.loadAsync().then(e):s()},n=0;s=()=>{let e=t[n++];if("function"==typeof e.init){let t=e.init(this.Reveal);t&&"function"==typeof t.then?t.then(a):a()}else a()},s()}}))}loadAsync(){return this.state="loaded",this.asyncDependencies.length&&this.asyncDependencies.forEach((e=>{D(e.src,e.callback)})),Promise.resolve()}registerPlugin(e){2===arguments.length&&"string"==typeof arguments[0]?(e=arguments[1]).id=arguments[0]:"function"==typeof e&&(e=e());let t=e.id;"string"!=typeof t?console.warn("Unrecognized plugin format; can't find plugin.id",e):void 0===this.registeredPlugins[t]?(this.registeredPlugins[t]=e,"loaded"===this.state&&"function"==typeof e.init&&e.init(this.Reveal)):console.warn('reveal.js: "'+t+'" plugin has already been registered')}hasPlugin(e){return!!this.registeredPlugins[e]}getPlugin(e){return this.registeredPlugins[e]}getRegisteredPlugins(){return this.registeredPlugins}destroy(){Object.values(this.registeredPlugins).forEach((e=>{"function"==typeof e.destroy&&e.destroy()})),this.registeredPlugins={},this.asyncDependencies=[]}}class z{constructor(e){this.Reveal=e,this.touchStartX=0,this.touchStartY=0,this.touchStartCount=0,this.touchCaptured=!1,this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.onTouchStart=this.onTouchStart.bind(this),this.onTouchMove=this.onTouchMove.bind(this),this.onTouchEnd=this.onTouchEnd.bind(this)}bind(){let e=this.Reveal.getRevealElement();"onpointerdown"in window?(e.addEventListener("pointerdown",this.onPointerDown,!1),e.addEventListener("pointermove",this.onPointerMove,!1),e.addEventListener("pointerup",this.onPointerUp,!1)):window.navigator.msPointerEnabled?(e.addEventListener("MSPointerDown",this.onPointerDown,!1),e.addEventListener("MSPointerMove",this.onPointerMove,!1),e.addEventListener("MSPointerUp",this.onPointerUp,!1)):(e.addEventListener("touchstart",this.onTouchStart,!1),e.addEventListener("touchmove",this.onTouchMove,!1),e.addEventListener("touchend",this.onTouchEnd,!1))}unbind(){let e=this.Reveal.getRevealElement();e.removeEventListener("pointerdown",this.onPointerDown,!1),e.removeEventListener("pointermove",this.onPointerMove,!1),e.removeEventListener("pointerup",this.onPointerUp,!1),e.removeEventListener("MSPointerDown",this.onPointerDown,!1),e.removeEventListener("MSPointerMove",this.onPointerMove,!1),e.removeEventListener("MSPointerUp",this.onPointerUp,!1),e.removeEventListener("touchstart",this.onTouchStart,!1),e.removeEventListener("touchmove",this.onTouchMove,!1),e.removeEventListener("touchend",this.onTouchEnd,!1)}isSwipePrevented(e){if(n(e,"video, audio"))return!0;for(;e&&"function"==typeof e.hasAttribute;){if(e.hasAttribute("data-prevent-swipe"))return!0;e=e.parentNode}return!1}onTouchStart(e){if(this.isSwipePrevented(e.target))return!0;this.touchStartX=e.touches[0].clientX,this.touchStartY=e.touches[0].clientY,this.touchStartCount=e.touches.length}onTouchMove(e){if(this.isSwipePrevented(e.target))return!0;let t=this.Reveal.getConfig();if(this.touchCaptured)g&&e.preventDefault();else{this.Reveal.onUserInput(e);let i=e.touches[0].clientX,s=e.touches[0].clientY;if(1===e.touches.length&&2!==this.touchStartCount){let a=this.Reveal.availableRoutes({includeFragments:!0}),n=i-this.touchStartX,r=s-this.touchStartY;n>40&&Math.abs(n)>Math.abs(r)?(this.touchCaptured=!0,"linear"===t.navigationMode?t.rtl?this.Reveal.next():this.Reveal.prev():this.Reveal.left()):n<-40&&Math.abs(n)>Math.abs(r)?(this.touchCaptured=!0,"linear"===t.navigationMode?t.rtl?this.Reveal.prev():this.Reveal.next():this.Reveal.right()):r>40&&a.up?(this.touchCaptured=!0,"linear"===t.navigationMode?this.Reveal.prev():this.Reveal.up()):r<-40&&a.down&&(this.touchCaptured=!0,"linear"===t.navigationMode?this.Reveal.next():this.Reveal.down()),t.embedded?(this.touchCaptured||this.Reveal.isVerticalSlide())&&e.preventDefault():e.preventDefault()}}}onTouchEnd(e){this.touchCaptured=!1}onPointerDown(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],this.onTouchStart(e))}onPointerMove(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],this.onTouchMove(e))}onPointerUp(e){e.pointerType!==e.MSPOINTER_TYPE_TOUCH&&"touch"!==e.pointerType||(e.touches=[{clientX:e.clientX,clientY:e.clientY}],this.onTouchEnd(e))}}const q="focus",O="blur";class W{constructor(e){this.Reveal=e,this.onRevealPointerDown=this.onRevealPointerDown.bind(this),this.onDocumentPointerDown=this.onDocumentPointerDown.bind(this)}configure(e,t){e.embedded?this.blur():(this.focus(),this.unbind())}bind(){this.Reveal.getConfig().embedded&&this.Reveal.getRevealElement().addEventListener("pointerdown",this.onRevealPointerDown,!1)}unbind(){this.Reveal.getRevealElement().removeEventListener("pointerdown",this.onRevealPointerDown,!1),document.removeEventListener("pointerdown",this.onDocumentPointerDown,!1)}focus(){this.state!==q&&(this.Reveal.getRevealElement().classList.add("focused"),document.addEventListener("pointerdown",this.onDocumentPointerDown,!1)),this.state=q}blur(){this.state!==O&&(this.Reveal.getRevealElement().classList.remove("focused"),document.removeEventListener("pointerdown",this.onDocumentPointerDown,!1)),this.state=O}isFocused(){return this.state===q}destroy(){this.Reveal.getRevealElement().classList.remove("focused")}onRevealPointerDown(e){this.focus()}onDocumentPointerDown(e){let t=r(e.target,".reveal");t&&t===this.Reveal.getRevealElement()||this.blur()}}class U{constructor(e){this.Reveal=e}render(){this.element=document.createElement("div"),this.element.className="speaker-notes",this.element.setAttribute("data-prevent-swipe",""),this.element.setAttribute("tabindex","0"),this.Reveal.getRevealElement().appendChild(this.element)}configure(e,t){e.showNotes&&this.element.setAttribute("data-layout","string"==typeof e.showNotes?e.showNotes:"inline")}update(){this.Reveal.getConfig().showNotes&&this.element&&this.Reveal.getCurrentSlide()&&!this.Reveal.isScrollView()&&!this.Reveal.isPrintView()&&(this.element.innerHTML=this.getSlideNotes()||'No notes on this slide.')}updateVisibility(){this.Reveal.getConfig().showNotes&&this.hasNotes()&&!this.Reveal.isScrollView()&&!this.Reveal.isPrintView()?this.Reveal.getRevealElement().classList.add("show-notes"):this.Reveal.getRevealElement().classList.remove("show-notes")}hasNotes(){return this.Reveal.getSlidesElement().querySelectorAll("[data-notes], aside.notes").length>0}isSpeakerNotesWindow(){return!!window.location.search.match(/receiver/gi)}getSlideNotes(e=this.Reveal.getCurrentSlide()){if(e.hasAttribute("data-notes"))return e.getAttribute("data-notes");let t=e.querySelectorAll("aside.notes");return t?Array.from(t).map((e=>e.innerHTML)).join("\n"):null}destroy(){this.element.remove()}}class V{constructor(e,t){this.diameter=100,this.diameter2=this.diameter/2,this.thickness=6,this.playing=!1,this.progress=0,this.progressOffset=1,this.container=e,this.progressCheck=t,this.canvas=document.createElement("canvas"),this.canvas.className="playback",this.canvas.width=this.diameter,this.canvas.height=this.diameter,this.canvas.style.width=this.diameter2+"px",this.canvas.style.height=this.diameter2+"px",this.context=this.canvas.getContext("2d"),this.container.appendChild(this.canvas),this.render()}setPlaying(e){const t=this.playing;this.playing=e,!t&&this.playing?this.animate():this.render()}animate(){const e=this.progress;this.progress=this.progressCheck(),e>.8&&this.progress<.2&&(this.progressOffset=this.progress),this.render(),this.playing&&requestAnimationFrame(this.animate.bind(this))}render(){let e=this.playing?this.progress:0,t=this.diameter2-this.thickness,i=this.diameter2,s=this.diameter2,a=28;this.progressOffset+=.1*(1-this.progressOffset);const n=-Math.PI/2+e*(2*Math.PI),r=-Math.PI/2+this.progressOffset*(2*Math.PI);this.context.save(),this.context.clearRect(0,0,this.diameter,this.diameter),this.context.beginPath(),this.context.arc(i,s,t+4,0,2*Math.PI,!1),this.context.fillStyle="rgba( 0, 0, 0, 0.4 )",this.context.fill(),this.context.beginPath(),this.context.arc(i,s,t,0,2*Math.PI,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="rgba( 255, 255, 255, 0.2 )",this.context.stroke(),this.playing&&(this.context.beginPath(),this.context.arc(i,s,t,r,n,!1),this.context.lineWidth=this.thickness,this.context.strokeStyle="#fff",this.context.stroke()),this.context.translate(i-14,s-14),this.playing?(this.context.fillStyle="#fff",this.context.fillRect(0,0,10,a),this.context.fillRect(18,0,10,a)):(this.context.beginPath(),this.context.translate(4,0),this.context.moveTo(0,0),this.context.lineTo(24,14),this.context.lineTo(0,a),this.context.fillStyle="#fff",this.context.fill()),this.context.restore()}on(e,t){this.canvas.addEventListener(e,t,!1)}off(e,t){this.canvas.removeEventListener(e,t,!1)}destroy(){this.playing=!1,this.canvas.parentNode&&this.container.removeChild(this.canvas)}}var j={width:960,height:700,margin:.01,minScale:.2,maxScale:2,controls:!0,controlsTutorial:!0,controlsLayout:"bottom-right",controlsBackArrows:"faded",progress:!0,slideNumber:!0,showSlideNumber:"all",hashOneBasedIndex:!1,hash:!1,respondToHashChanges:!0,jumpToSlide:!0,history:!1,keyboard:!0,keyboardCondition:null,disableLayout:!1,overview:!0,center:!0,touch:!0,loop:!1,rtl:!1,navigationMode:"default",shuffle:!1,fragments:!0,fragmentInURL:!0,embedded:!1,help:!0,pause:!0,showNotes:!1,showHiddenSlides:!1,autoPlayMedia:null,preloadIframes:null,autoAnimate:!0,autoAnimateMatcher:null,autoAnimateEasing:"ease",autoAnimateDuration:1,autoAnimateUnmatched:!0,autoAnimateStyles:["opacity","color","background-color","padding","font-size","line-height","letter-spacing","border-width","border-color","border-radius","outline","outline-offset"],autoSlide:0,autoSlideStoppable:!0,autoSlideMethod:null,defaultTiming:null,mouseWheel:!1,previewLinks:!1,postMessage:!0,postMessageEvents:!1,focusBodyOnPageVisibilityChange:!0,transition:"slide",transitionSpeed:"default",backgroundTransition:"fade",parallaxBackgroundImage:"",parallaxBackgroundSize:"",parallaxBackgroundRepeat:"",parallaxBackgroundPosition:"",parallaxBackgroundHorizontal:null,parallaxBackgroundVertical:null,view:null,scrollLayout:"full",scrollSnap:"mandatory",scrollProgress:"auto",scrollActivationWidth:435,pdfMaxPagesPerSlide:Number.POSITIVE_INFINITY,pdfSeparateFragments:!0,pdfPageHeightOffset:-1,viewDistance:3,mobileViewDistance:2,display:"block",hideInactiveCursor:!0,hideCursorTime:5e3,sortFragmentsOnSync:!0,dependencies:[],plugins:[]};const K="5.0.5";function $(n,o){arguments.length<2&&(o=arguments[0],n=document.querySelector(".reveal"));const l={};let c,h,g,p,w,A={},k=!1,D={hasNavigatedHorizontally:!1,hasNavigatedVertically:!1},q=[],O=1,$={layout:"",overview:""},X={},Y="idle",_=0,J=0,G=-1,Q=!1,Z=new v(l),ee=new E(l),te=new S(l),ie=new L(l),se=new R(l),ae=new C(l),ne=new x(l),re=new P(l),oe=new T(l),le=new N(l),de=new M(l),ce=new I(l),he=new B(l),ue=new H(l),ge=new F(l),pe=new W(l),ve=new z(l),me=new U(l);function fe(){k=!0,A.showHiddenSlides||t(X.wrapper,'section[data-visibility="hidden"]').forEach((e=>{const t=e.parentNode;1===t.childElementCount&&/section/i.test(t.nodeName)?t.remove():e.remove()})),function(){X.slides.classList.add("no-transition"),u?X.wrapper.classList.add("no-hover"):X.wrapper.classList.remove("no-hover");se.render(),ee.render(),te.render(),ce.render(),he.render(),me.render(),X.pauseOverlay=((e,t,i,s="")=>{let a=e.querySelectorAll("."+i);for(let t=0;tResume presentation':null),X.statusElement=function(){let e=X.wrapper.querySelector(".aria-status");e||(e=document.createElement("div"),e.style.position="absolute",e.style.height="1px",e.style.width="1px",e.style.overflow="hidden",e.style.clip="rect( 1px, 1px, 1px, 1px )",e.classList.add("aria-status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),X.wrapper.appendChild(e));return e}(),X.wrapper.setAttribute("role","application")}(),A.postMessage&&window.addEventListener("message",St,!1),setInterval((()=>{(!ae.isActive()&&0!==X.wrapper.scrollTop||0!==X.wrapper.scrollLeft)&&(X.wrapper.scrollTop=0,X.wrapper.scrollLeft=0)}),1e3),document.addEventListener("fullscreenchange",Ct),document.addEventListener("webkitfullscreenchange",Ct),nt().forEach((e=>{t(e,"section").forEach(((e,t)=>{t>0&&(e.classList.remove("present"),e.classList.remove("past"),e.classList.add("future"),e.setAttribute("aria-hidden","true"))}))})),we(),se.update(!0),function(){const e="print"===A.view,t="scroll"===A.view||"reader"===A.view;(e||t)&&(e?Se():ve.unbind(),X.viewport.classList.add("loading-scroll-mode"),e?"complete"===document.readyState?ne.activate():window.addEventListener("load",(()=>ne.activate())):ae.activate())}(),de.readURL(),setTimeout((()=>{X.slides.classList.remove("no-transition"),X.wrapper.classList.add("ready"),Le({type:"ready",data:{indexh:c,indexv:h,currentSlide:p}})}),1)}function ye(e){X.statusElement.textContent=e}function be(e){let t="";if(3===e.nodeType)t+=e.textContent;else if(1===e.nodeType){let i=e.getAttribute("aria-hidden"),s="none"===window.getComputedStyle(e).display;"true"===i||s||Array.from(e.childNodes).forEach((e=>{t+=be(e)}))}return t=t.trim(),""===t?"":t+" "}function we(t){const s={...A};if("object"==typeof t&&e(A,t),!1===l.isReady())return;const a=X.wrapper.querySelectorAll(m).length;X.wrapper.classList.remove(s.transition),X.wrapper.classList.add(A.transition),X.wrapper.setAttribute("data-transition-speed",A.transitionSpeed),X.wrapper.setAttribute("data-background-transition",A.backgroundTransition),X.viewport.style.setProperty("--slide-width","string"==typeof A.width?A.width:A.width+"px"),X.viewport.style.setProperty("--slide-height","string"==typeof A.height?A.height:A.height+"px"),A.shuffle&&Je(),i(X.wrapper,"embedded",A.embedded),i(X.wrapper,"rtl",A.rtl),i(X.wrapper,"center",A.center),!1===A.pause&&je(),A.previewLinks?(Pe(),Te("[data-preview-link=false]")):(Te(),Pe("[data-preview-link]:not([data-preview-link=false])")),ie.reset(),w&&(w.destroy(),w=null),a>1&&A.autoSlide&&A.autoSlideStoppable&&(w=new V(X.wrapper,(()=>Math.min(Math.max((Date.now()-G)/_,0),1))),w.on("click",Pt),Q=!1),"default"!==A.navigationMode?X.wrapper.setAttribute("data-navigation-mode",A.navigationMode):X.wrapper.removeAttribute("data-navigation-mode"),me.configure(A,s),pe.configure(A,s),ue.configure(A,s),ce.configure(A,s),he.configure(A,s),le.configure(A,s),re.configure(A,s),ee.configure(A,s),_e()}function Ee(){window.addEventListener("resize",kt,!1),A.touch&&ve.bind(),A.keyboard&&le.bind(),A.progress&&he.bind(),A.respondToHashChanges&&de.bind(),ce.bind(),pe.bind(),X.slides.addEventListener("click",Rt,!1),X.slides.addEventListener("transitionend",At,!1),X.pauseOverlay.addEventListener("click",je,!1),A.focusBodyOnPageVisibilityChange&&document.addEventListener("visibilitychange",Lt,!1)}function Se(){ve.unbind(),pe.unbind(),le.unbind(),ce.unbind(),he.unbind(),de.unbind(),window.removeEventListener("resize",kt,!1),X.slides.removeEventListener("click",Rt,!1),X.slides.removeEventListener("transitionend",At,!1),X.pauseOverlay.removeEventListener("click",je,!1)}function Ae(e,t,i){n.addEventListener(e,t,i)}function Re(e,t,i){n.removeEventListener(e,t,i)}function ke(e){"string"==typeof e.layout&&($.layout=e.layout),"string"==typeof e.overview&&($.overview=e.overview),$.layout?a(X.slides,$.layout+" "+$.overview):a(X.slides,$.overview)}function Le({target:t=X.wrapper,type:i,data:s,bubbles:a=!0}){let n=document.createEvent("HTMLEvents",1,2);return n.initEvent(i,a,!0),e(n,s),t.dispatchEvent(n),t===X.wrapper&&xe(i),n}function Ce(e){Le({type:"slidechanged",data:{indexh:c,indexv:h,previousSlide:g,currentSlide:p,origin:e}})}function xe(t,i){if(A.postMessageEvents&&window.parent!==window.self){let s={namespace:"reveal",eventName:t,state:ht()};e(s,i),window.parent.postMessage(JSON.stringify(s),"*")}}function Pe(e="a"){Array.from(X.wrapper.querySelectorAll(e)).forEach((e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.addEventListener("click",xt,!1)}))}function Te(e="a"){Array.from(X.wrapper.querySelectorAll(e)).forEach((e=>{/^(http|www)/gi.test(e.getAttribute("href"))&&e.removeEventListener("click",xt,!1)}))}function Ne(e){Ie(),X.overlay=document.createElement("div"),X.overlay.classList.add("overlay"),X.overlay.classList.add("overlay-preview"),X.wrapper.appendChild(X.overlay),X.overlay.innerHTML=`
\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\tUnable to load iframe. This is likely due to the site's policy (x-frame-options).\n\t\t\t\t\n\t\t\t
`,X.overlay.querySelector("iframe").addEventListener("load",(e=>{X.overlay.classList.add("loaded")}),!1),X.overlay.querySelector(".close").addEventListener("click",(e=>{Ie(),e.preventDefault()}),!1),X.overlay.querySelector(".external").addEventListener("click",(e=>{Ie()}),!1)}function Me(){if(A.help){Ie(),X.overlay=document.createElement("div"),X.overlay.classList.add("overlay"),X.overlay.classList.add("overlay-help"),X.wrapper.appendChild(X.overlay);let e='

Keyboard Shortcuts


',t=le.getShortcuts(),i=le.getBindings();e+="";for(let i in t)e+=``;for(let t in i)i[t].key&&i[t].description&&(e+=``);e+="
KEYACTION
${i}${t[i]}
${i[t].key}${i[t].description}
",X.overlay.innerHTML=`\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
${e}
\n\t\t\t\t
\n\t\t\t`,X.overlay.querySelector(".close").addEventListener("click",(e=>{Ie(),e.preventDefault()}),!1)}}function Ie(){return!!X.overlay&&(X.overlay.parentNode.removeChild(X.overlay),X.overlay=null,!0)}function Be(){if(X.wrapper&&!ne.isActive()){const e=X.viewport.offsetWidth,t=X.viewport.offsetHeight;if(!A.disableLayout){u&&!A.embedded&&document.documentElement.style.setProperty("--vh",.01*window.innerHeight+"px");const i=ae.isActive()?De(e,t):De(),s=O;He(A.width,A.height),X.slides.style.width=i.width+"px",X.slides.style.height=i.height+"px",O=Math.min(i.presentationWidth/i.width,i.presentationHeight/i.height),O=Math.max(O,A.minScale),O=Math.min(O,A.maxScale),1===O||ae.isActive()?(X.slides.style.zoom="",X.slides.style.left="",X.slides.style.top="",X.slides.style.bottom="",X.slides.style.right="",ke({layout:""})):(X.slides.style.zoom="",X.slides.style.left="50%",X.slides.style.top="50%",X.slides.style.bottom="auto",X.slides.style.right="auto",ke({layout:"translate(-50%, -50%) scale("+O+")"}));const a=Array.from(X.wrapper.querySelectorAll(m));for(let e=0,t=a.length;e0&&e.presentationWidth<=A.scrollActivationWidth?ae.isActive()||(se.create(),ae.activate()):ae.isActive()&&ae.deactivate()}}(),X.viewport.style.setProperty("--slide-scale",O),X.viewport.style.setProperty("--viewport-width",e+"px"),X.viewport.style.setProperty("--viewport-height",t+"px"),ae.layout(),he.update(),se.updateParallax(),oe.isActive()&&oe.update()}}function He(e,i){t(X.slides,"section > .stretch, section > .r-stretch").forEach((t=>{let s=((e,t=0)=>{if(e){let i,s=e.style.height;return e.style.height="0px",e.parentNode.style.height="auto",i=t-e.parentNode.offsetHeight,e.style.height=s+"px",e.parentNode.style.removeProperty("height"),i}return t})(t,i);if(/(img|video)/gi.test(t.nodeName)){const i=t.naturalWidth||t.videoWidth,a=t.naturalHeight||t.videoHeight,n=Math.min(e/i,s/a);t.style.width=i*n+"px",t.style.height=a*n+"px"}else t.style.width=e+"px",t.style.height=s+"px"}))}function De(e,t){let i=A.width,s=A.height;A.disableLayout&&(i=X.slides.offsetWidth,s=X.slides.offsetHeight);const a={width:i,height:s,presentationWidth:e||X.wrapper.offsetWidth,presentationHeight:t||X.wrapper.offsetHeight};return a.presentationWidth-=a.presentationWidth*A.margin,a.presentationHeight-=a.presentationHeight*A.margin,"string"==typeof a.width&&/%$/.test(a.width)&&(a.width=parseInt(a.width,10)/100*a.presentationWidth),"string"==typeof a.height&&/%$/.test(a.height)&&(a.height=parseInt(a.height,10)/100*a.presentationHeight),a}function Fe(e,t){"object"==typeof e&&"function"==typeof e.setAttribute&&e.setAttribute("data-previous-indexv",t||0)}function ze(e){if("object"==typeof e&&"function"==typeof e.setAttribute&&e.classList.contains("stack")){const t=e.hasAttribute("data-start-indexv")?"data-start-indexv":"data-previous-indexv";return parseInt(e.getAttribute(t)||0,10)}return 0}function qe(e=p){return e&&e.parentNode&&!!e.parentNode.nodeName.match(/section/i)}function Oe(){return!(!p||!qe(p))&&!p.nextElementSibling}function We(){return 0===c&&0===h}function Ue(){return!!p&&(!p.nextElementSibling&&(!qe(p)||!p.parentNode.nextElementSibling))}function Ve(){if(A.pause){const e=X.wrapper.classList.contains("paused");gt(),X.wrapper.classList.add("paused"),!1===e&&Le({type:"paused"})}}function je(){const e=X.wrapper.classList.contains("paused");X.wrapper.classList.remove("paused"),ut(),e&&Le({type:"resumed"})}function Ke(e){"boolean"==typeof e?e?Ve():je():$e()?je():Ve()}function $e(){return X.wrapper.classList.contains("paused")}function Xe(e,i,s,a){if(Le({type:"beforeslidechange",data:{indexh:void 0===e?c:e,indexv:void 0===i?h:i,origin:a}}).defaultPrevented)return;g=p;const n=X.wrapper.querySelectorAll(f);if(ae.isActive()){const t=ae.getSlideByIndices(e,i);return void(t&&ae.scrollToSlide(t))}if(0===n.length)return;void 0!==i||oe.isActive()||(i=ze(n[e])),g&&g.parentNode&&g.parentNode.classList.contains("stack")&&Fe(g.parentNode,h);const r=q.concat();q.length=0;let o=c||0,l=h||0;c=Ge(f,void 0===e?c:e),h=Ge(y,void 0===i?h:i);let d=c!==o||h!==l;d||(g=null);let u=n[c],v=u.querySelectorAll("section");p=v[h]||u;let m=!1;d&&g&&p&&!oe.isActive()&&(Y="running",m=Ye(g,p,o,l),m&&X.slides.classList.add("disable-slide-transitions")),et(),Be(),oe.isActive()&&oe.update(),void 0!==s&&re.goto(s),g&&g!==p&&(g.classList.remove("present"),g.setAttribute("aria-hidden","true"),We()&&setTimeout((()=>{t(X.wrapper,f+".stack").forEach((e=>{Fe(e,0)}))}),0));e:for(let e=0,t=q.length;e{ye(be(p))})),he.update(),ce.update(),me.update(),se.update(),se.updateParallax(),ee.update(),re.update(),de.writeURL(),ut(),m&&(setTimeout((()=>{X.slides.classList.remove("disable-slide-transitions")}),0),A.autoAnimate&&ie.run(g,p))}function Ye(e,t,i,s){return e.hasAttribute("data-auto-animate")&&t.hasAttribute("data-auto-animate")&&e.getAttribute("data-auto-animate-id")===t.getAttribute("data-auto-animate-id")&&!(c>i||h>s?t:e).hasAttribute("data-auto-animate-restart")}function _e(){Se(),Ee(),Be(),_=A.autoSlide,ut(),se.create(),de.writeURL(),!0===A.sortFragmentsOnSync&&re.sortAll(),ce.update(),he.update(),et(),me.update(),me.updateVisibility(),se.update(!0),ee.update(),Z.formatEmbeddedContent(),!1===A.autoPlayMedia?Z.stopEmbeddedContent(p,{unloadIframes:!1}):Z.startEmbeddedContent(p),oe.isActive()&&oe.layout()}function Je(e=nt()){e.forEach(((t,i)=>{let s=e[Math.floor(Math.random()*e.length)];s.parentNode===t.parentNode&&t.parentNode.insertBefore(t,s);let a=t.querySelectorAll("section");a.length&&Je(a)}))}function Ge(e,i){let s=t(X.wrapper,e),a=s.length,n=ae.isActive()||ne.isActive(),r=!1,o=!1;if(a){A.loop&&(i>=a&&(r=!0),(i%=a)<0&&(i=a+i,o=!0)),i=Math.max(Math.min(i,a-1),0);for(let e=0;ei?(t.classList.add(a?"past":"future"),A.fragments&&Ze(t)):e===i&&A.fragments&&(r?Ze(t):o&&Qe(t))}let e=s[i],t=e.classList.contains("present");e.classList.add("present"),e.removeAttribute("hidden"),e.removeAttribute("aria-hidden"),t||Le({target:e,type:"visible",bubbles:!1});let l=e.getAttribute("data-state");l&&(q=q.concat(l.split(" ")))}else i=0;return i}function Qe(e){t(e,".fragment").forEach((e=>{e.classList.add("visible"),e.classList.remove("current-fragment")}))}function Ze(e){t(e,".fragment.visible").forEach((e=>{e.classList.remove("visible","current-fragment")}))}function et(){let e,i,s=nt(),a=s.length;if(a&&void 0!==c){let n=oe.isActive()?10:A.viewDistance;u&&(n=oe.isActive()?6:A.mobileViewDistance),ne.isActive()&&(n=Number.MAX_VALUE);for(let r=0;r0,right:c0,down:h1&&(s.left=!0,s.right=!0),i.length>1&&(s.up=!0,s.down=!0)),t.length>1&&"linear"===A.navigationMode&&(s.right=s.right||s.down,s.left=s.left||s.up),!0===e){let e=re.availableRoutes();s.left=s.left||e.prev,s.up=s.up||e.prev,s.down=s.down||e.next,s.right=s.right||e.next}if(A.rtl){let e=s.left;s.left=s.right,s.right=e}return s}function it(e=p){let t=nt(),i=0;e:for(let s=0;s0){let e=p.querySelector(".current-fragment");i=e&&e.hasAttribute("data-fragment-index")?parseInt(e.getAttribute("data-fragment-index"),10):p.querySelectorAll(".fragment.visible").length-1}}return{h:s,v:a,f:i}}function at(){return t(X.wrapper,m+':not(.stack):not([data-visibility="uncounted"])')}function nt(){return t(X.wrapper,f)}function rt(){return t(X.wrapper,".slides>section>section")}function ot(){return nt().length>1}function lt(){return rt().length>1}function dt(){return at().length}function ct(e,t){let i=nt()[e],s=i&&i.querySelectorAll("section");return s&&s.length&&"number"==typeof t?s?s[t]:void 0:i}function ht(){let e=st();return{indexh:e.h,indexv:e.v,indexf:e.f,paused:$e(),overview:oe.isActive()}}function ut(){if(gt(),p&&!1!==A.autoSlide){let e=p.querySelector(".current-fragment[data-autoslide]"),i=e?e.getAttribute("data-autoslide"):null,s=p.parentNode?p.parentNode.getAttribute("data-autoslide"):null,a=p.getAttribute("data-autoslide");i?_=parseInt(i,10):a?_=parseInt(a,10):s?_=parseInt(s,10):(_=A.autoSlide,0===p.querySelectorAll(".fragment").length&&t(p,"video, audio").forEach((e=>{e.hasAttribute("data-autoplay")&&_&&1e3*e.duration/e.playbackRate>_&&(_=1e3*e.duration/e.playbackRate+1e3)}))),!_||Q||$e()||oe.isActive()||Ue()&&!re.availableRoutes().next&&!0!==A.loop||(J=setTimeout((()=>{"function"==typeof A.autoSlideMethod?A.autoSlideMethod():Et(),ut()}),_),G=Date.now()),w&&w.setPlaying(-1!==J)}}function gt(){clearTimeout(J),J=-1}function pt(){_&&!Q&&(Q=!0,Le({type:"autoslidepaused"}),clearTimeout(J),w&&w.setPlaying(!1))}function vt(){_&&Q&&(Q=!1,Le({type:"autoslideresumed"}),ut())}function mt({skipFragments:e=!1}={}){if(D.hasNavigatedHorizontally=!0,ae.isActive())return ae.prev();A.rtl?(oe.isActive()||e||!1===re.next())&&tt().left&&Xe(c+1,"grid"===A.navigationMode?h:void 0):(oe.isActive()||e||!1===re.prev())&&tt().left&&Xe(c-1,"grid"===A.navigationMode?h:void 0)}function ft({skipFragments:e=!1}={}){if(D.hasNavigatedHorizontally=!0,ae.isActive())return ae.next();A.rtl?(oe.isActive()||e||!1===re.prev())&&tt().right&&Xe(c-1,"grid"===A.navigationMode?h:void 0):(oe.isActive()||e||!1===re.next())&&tt().right&&Xe(c+1,"grid"===A.navigationMode?h:void 0)}function yt({skipFragments:e=!1}={}){if(ae.isActive())return ae.prev();(oe.isActive()||e||!1===re.prev())&&tt().up&&Xe(c,h-1)}function bt({skipFragments:e=!1}={}){if(D.hasNavigatedVertically=!0,ae.isActive())return ae.next();(oe.isActive()||e||!1===re.next())&&tt().down&&Xe(c,h+1)}function wt({skipFragments:e=!1}={}){if(ae.isActive())return ae.prev();if(e||!1===re.prev())if(tt().up)yt({skipFragments:e});else{let i;if(i=A.rtl?t(X.wrapper,f+".future").pop():t(X.wrapper,f+".past").pop(),i&&i.classList.contains("stack")){let e=i.querySelectorAll("section").length-1||void 0;Xe(c-1,e)}else mt({skipFragments:e})}}function Et({skipFragments:e=!1}={}){if(D.hasNavigatedHorizontally=!0,D.hasNavigatedVertically=!0,ae.isActive())return ae.next();if(e||!1===re.next()){let t=tt();t.down&&t.right&&A.loop&&Oe()&&(t.down=!1),t.down?bt({skipFragments:e}):A.rtl?mt({skipFragments:e}):ft({skipFragments:e})}}function St(e){let t=e.data;if("string"==typeof t&&"{"===t.charAt(0)&&"}"===t.charAt(t.length-1)&&(t=JSON.parse(t),t.method&&"function"==typeof l[t.method]))if(!1===b.test(t.method)){const e=l[t.method].apply(l,t.args);xe("callback",{method:t.method,result:e})}else console.warn('reveal.js: "'+t.method+'" is is blacklisted from the postMessage API')}function At(e){"running"===Y&&/section/gi.test(e.target.nodeName)&&(Y="idle",Le({type:"slidetransitionend",data:{indexh:c,indexv:h,previousSlide:g,currentSlide:p}}))}function Rt(e){const t=r(e.target,'a[href^="#"]');if(t){const i=t.getAttribute("href"),s=de.getIndicesFromHash(i);s&&(l.slide(s.h,s.v,s.f),e.preventDefault())}}function kt(e){Be()}function Lt(e){!1===document.hidden&&document.activeElement!==document.body&&("function"==typeof document.activeElement.blur&&document.activeElement.blur(),document.body.focus())}function Ct(e){(document.fullscreenElement||document.webkitFullscreenElement)===X.wrapper&&(e.stopImmediatePropagation(),setTimeout((()=>{l.layout(),l.focus.focus()}),1))}function xt(e){if(e.currentTarget&&e.currentTarget.hasAttribute("href")){let t=e.currentTarget.getAttribute("href");t&&(Ne(t),e.preventDefault())}}function Pt(e){Ue()&&!1===A.loop?(Xe(0,0),vt()):Q?vt():pt()}const Tt={VERSION:K,initialize:function(e){if(!n)throw'Unable to find presentation root (
).';if(X.wrapper=n,X.slides=n.querySelector(".slides"),!X.slides)throw'Unable to find slides container (
).';return A={...j,...A,...o,...e,...d()},/print-pdf/gi.test(window.location.search)&&(A.view="print"),function(){!0===A.embedded?X.viewport=r(n,".reveal-viewport")||n:(X.viewport=document.body,document.documentElement.classList.add("reveal-full-page"));X.viewport.classList.add("reveal-viewport")}(),window.addEventListener("load",Be,!1),ge.load(A.plugins,A.dependencies).then(fe),new Promise((e=>l.on("ready",e)))},configure:we,destroy:function(){Se(),gt(),Te(),me.destroy(),pe.destroy(),ge.destroy(),ue.destroy(),ce.destroy(),he.destroy(),se.destroy(),ee.destroy(),te.destroy(),document.removeEventListener("fullscreenchange",Ct),document.removeEventListener("webkitfullscreenchange",Ct),document.removeEventListener("visibilitychange",Lt,!1),window.removeEventListener("message",St,!1),window.removeEventListener("load",Be,!1),X.pauseOverlay&&X.pauseOverlay.remove(),X.statusElement&&X.statusElement.remove(),document.documentElement.classList.remove("reveal-full-page"),X.wrapper.classList.remove("ready","center","has-horizontal-slides","has-vertical-slides"),X.wrapper.removeAttribute("data-transition-speed"),X.wrapper.removeAttribute("data-background-transition"),X.viewport.classList.remove("reveal-viewport"),X.viewport.style.removeProperty("--slide-width"),X.viewport.style.removeProperty("--slide-height"),X.slides.style.removeProperty("width"),X.slides.style.removeProperty("height"),X.slides.style.removeProperty("zoom"),X.slides.style.removeProperty("left"),X.slides.style.removeProperty("top"),X.slides.style.removeProperty("bottom"),X.slides.style.removeProperty("right"),X.slides.style.removeProperty("transform"),Array.from(X.wrapper.querySelectorAll(m)).forEach((e=>{e.style.removeProperty("display"),e.style.removeProperty("top"),e.removeAttribute("hidden"),e.removeAttribute("aria-hidden")}))},sync:_e,syncSlide:function(e=p){se.sync(e),re.sync(e),Z.load(e),se.update(),me.update()},syncFragments:re.sync.bind(re),slide:Xe,left:mt,right:ft,up:yt,down:bt,prev:wt,next:Et,navigateLeft:mt,navigateRight:ft,navigateUp:yt,navigateDown:bt,navigatePrev:wt,navigateNext:Et,navigateFragment:re.goto.bind(re),prevFragment:re.prev.bind(re),nextFragment:re.next.bind(re),on:Ae,off:Re,addEventListener:Ae,removeEventListener:Re,layout:Be,shuffle:Je,availableRoutes:tt,availableFragments:re.availableRoutes.bind(re),toggleHelp:function(e){"boolean"==typeof e?e?Me():Ie():X.overlay?Ie():Me()},toggleOverview:oe.toggle.bind(oe),toggleScrollView:ae.toggle.bind(ae),togglePause:Ke,toggleAutoSlide:function(e){"boolean"==typeof e?e?vt():pt():Q?vt():pt()},toggleJumpToSlide:function(e){"boolean"==typeof e?e?te.show():te.hide():te.isVisible()?te.hide():te.show()},isFirstSlide:We,isLastSlide:Ue,isLastVerticalSlide:Oe,isVerticalSlide:qe,isVerticalStack:function(e=p){return e.classList.contains(".stack")||null!==e.querySelector("section")},isPaused:$e,isAutoSliding:function(){return!(!_||Q)},isSpeakerNotes:me.isSpeakerNotesWindow.bind(me),isOverview:oe.isActive.bind(oe),isFocused:pe.isFocused.bind(pe),isScrollView:ae.isActive.bind(ae),isPrintView:ne.isActive.bind(ne),isReady:()=>k,loadSlide:Z.load.bind(Z),unloadSlide:Z.unload.bind(Z),startEmbeddedContent:()=>Z.startEmbeddedContent(p),stopEmbeddedContent:()=>Z.stopEmbeddedContent(p,{unloadIframes:!1}),showPreview:Ne,hidePreview:Ie,addEventListeners:Ee,removeEventListeners:Se,dispatchEvent:Le,getState:ht,setState:function(e){if("object"==typeof e){Xe(s(e.indexh),s(e.indexv),s(e.indexf));let t=s(e.paused),i=s(e.overview);"boolean"==typeof t&&t!==$e()&&Ke(t),"boolean"==typeof i&&i!==oe.isActive()&&oe.toggle(i)}},getProgress:function(){let e=dt(),t=it();if(p){let e=p.querySelectorAll(".fragment");if(e.length>0){let i=.9;t+=p.querySelectorAll(".fragment.visible").length/e.length*i}}return Math.min(t/(e-1),1)},getIndices:st,getSlidesAttributes:function(){return at().map((e=>{let t={};for(let i=0;ig,getCurrentSlide:()=>p,getSlideBackground:function(e,t){let i="number"==typeof e?ct(e,t):e;if(i)return i.slideBackgroundElement},getSlideNotes:me.getSlideNotes.bind(me),getSlides:at,getHorizontalSlides:nt,getVerticalSlides:rt,hasHorizontalSlides:ot,hasVerticalSlides:lt,hasNavigatedHorizontally:()=>D.hasNavigatedHorizontally,hasNavigatedVertically:()=>D.hasNavigatedVertically,shouldAutoAnimateBetween:Ye,addKeyBinding:le.addKeyBinding.bind(le),removeKeyBinding:le.removeKeyBinding.bind(le),triggerKey:le.triggerKey.bind(le),registerKeyboardShortcut:le.registerKeyboardShortcut.bind(le),getComputedSlideSize:De,setCurrentScrollPage:function(e,t,i){let s=c||0;c=t,h=i;const a=p!==e;g=p,p=e,p&&g&&A.autoAnimate&&Ye(g,p,s,h)&&ie.run(g,p),a&&(g&&(Z.stopEmbeddedContent(g),Z.stopEmbeddedContent(g.slideBackgroundElement)),Z.startEmbeddedContent(p),Z.startEmbeddedContent(p.slideBackgroundElement)),requestAnimationFrame((()=>{ye(be(p))})),Ce()},getScale:()=>O,getConfig:()=>A,getQueryHash:d,getSlidePath:de.getHash.bind(de),getRevealElement:()=>n,getSlidesElement:()=>X.slides,getViewportElement:()=>X.viewport,getBackgroundsElement:()=>se.element,registerPlugin:ge.registerPlugin.bind(ge),hasPlugin:ge.hasPlugin.bind(ge),getPlugin:ge.getPlugin.bind(ge),getPlugins:ge.getRegisteredPlugins.bind(ge)};return e(l,{...Tt,announceStatus:ye,getStatusText:be,focus:pe,scroll:ae,progress:he,controls:ce,location:de,overview:oe,fragments:re,backgrounds:se,slideContent:Z,slideNumber:ee,onUserInput:function(e){A.autoSlideStoppable&&pt()},closeOverlay:Ie,updateSlidesVisibility:et,layoutSlideContents:He,transformSlides:ke,cueAutoSlide:ut,cancelAutoSlide:gt}),Tt}let X=$,Y=[];X.initialize=e=>(Object.assign(X,new $(document.querySelector(".reveal"),e)),Y.map((e=>e(X))),X.initialize()),["configure","on","off","addEventListener","removeEventListener","registerPlugin"].forEach((e=>{X[e]=(...t)=>{Y.push((i=>i[e].call(null,...t)))}})),X.isReady=()=>!1,X.VERSION=K;export{X as default}; +//# sourceMappingURL=reveal.esm.js.map diff --git a/src/public/bash/dist/reveal.esm.js.map b/src/public/bash/dist/reveal.esm.js.map new file mode 100644 index 0000000..576a533 --- /dev/null +++ b/src/public/bash/dist/reveal.esm.js.map @@ -0,0 +1 @@ +{"version":3,"file":"reveal.esm.js","sources":["../js/utils/util.js","../js/utils/device.js","../node_modules/.pnpm/fitty@2.4.2/node_modules/fitty/dist/fitty.module.js","../js/controllers/slidecontent.js","../js/utils/constants.js","../js/controllers/slidenumber.js","../js/controllers/jumptoslide.js","../js/utils/color.js","../js/controllers/backgrounds.js","../js/controllers/autoanimate.js","../js/controllers/scrollview.js","../js/controllers/printview.js","../js/controllers/fragments.js","../js/controllers/overview.js","../js/controllers/keyboard.js","../js/controllers/location.js","../js/controllers/controls.js","../js/controllers/progress.js","../js/controllers/pointer.js","../js/utils/loader.js","../js/controllers/plugins.js","../js/controllers/touch.js","../js/controllers/focus.js","../js/controllers/notes.js","../js/components/playback.js","../js/config.js","../js/reveal.js","../js/index.js"],"sourcesContent":["/**\r\n * Extend object a with the properties of object b.\r\n * If there's a conflict, object b takes precedence.\r\n *\r\n * @param {object} a\r\n * @param {object} b\r\n */\r\nexport const extend = ( a, b ) => {\r\n\r\n\tfor( let i in b ) {\r\n\t\ta[ i ] = b[ i ];\r\n\t}\r\n\r\n\treturn a;\r\n\r\n}\r\n\r\n/**\r\n * querySelectorAll but returns an Array.\r\n */\r\nexport const queryAll = ( el, selector ) => {\r\n\r\n\treturn Array.from( el.querySelectorAll( selector ) );\r\n\r\n}\r\n\r\n/**\r\n * classList.toggle() with cross browser support\r\n */\r\nexport const toggleClass = ( el, className, value ) => {\r\n\tif( value ) {\r\n\t\tel.classList.add( className );\r\n\t}\r\n\telse {\r\n\t\tel.classList.remove( className );\r\n\t}\r\n}\r\n\r\n/**\r\n * Utility for deserializing a value.\r\n *\r\n * @param {*} value\r\n * @return {*}\r\n */\r\nexport const deserialize = ( value ) => {\r\n\r\n\tif( typeof value === 'string' ) {\r\n\t\tif( value === 'null' ) return null;\r\n\t\telse if( value === 'true' ) return true;\r\n\t\telse if( value === 'false' ) return false;\r\n\t\telse if( value.match( /^-?[\\d\\.]+$/ ) ) return parseFloat( value );\r\n\t}\r\n\r\n\treturn value;\r\n\r\n}\r\n\r\n/**\r\n * Measures the distance in pixels between point a\r\n * and point b.\r\n *\r\n * @param {object} a point with x/y properties\r\n * @param {object} b point with x/y properties\r\n *\r\n * @return {number}\r\n */\r\nexport const distanceBetween = ( a, b ) => {\r\n\r\n\tlet dx = a.x - b.x,\r\n\t\tdy = a.y - b.y;\r\n\r\n\treturn Math.sqrt( dx*dx + dy*dy );\r\n\r\n}\r\n\r\n/**\r\n * Applies a CSS transform to the target element.\r\n *\r\n * @param {HTMLElement} element\r\n * @param {string} transform\r\n */\r\nexport const transformElement = ( element, transform ) => {\r\n\r\n\telement.style.transform = transform;\r\n\r\n}\r\n\r\n/**\r\n * Element.matches with IE support.\r\n *\r\n * @param {HTMLElement} target The element to match\r\n * @param {String} selector The CSS selector to match\r\n * the element against\r\n *\r\n * @return {Boolean}\r\n */\r\nexport const matches = ( target, selector ) => {\r\n\r\n\tlet matchesMethod = target.matches || target.matchesSelector || target.msMatchesSelector;\r\n\r\n\treturn !!( matchesMethod && matchesMethod.call( target, selector ) );\r\n\r\n}\r\n\r\n/**\r\n * Find the closest parent that matches the given\r\n * selector.\r\n *\r\n * @param {HTMLElement} target The child element\r\n * @param {String} selector The CSS selector to match\r\n * the parents against\r\n *\r\n * @return {HTMLElement} The matched parent or null\r\n * if no matching parent was found\r\n */\r\nexport const closest = ( target, selector ) => {\r\n\r\n\t// Native Element.closest\r\n\tif( typeof target.closest === 'function' ) {\r\n\t\treturn target.closest( selector );\r\n\t}\r\n\r\n\t// Polyfill\r\n\twhile( target ) {\r\n\t\tif( matches( target, selector ) ) {\r\n\t\t\treturn target;\r\n\t\t}\r\n\r\n\t\t// Keep searching\r\n\t\ttarget = target.parentNode;\r\n\t}\r\n\r\n\treturn null;\r\n\r\n}\r\n\r\n/**\r\n * Handling the fullscreen functionality via the fullscreen API\r\n *\r\n * @see http://fullscreen.spec.whatwg.org/\r\n * @see https://developer.mozilla.org/en-US/docs/DOM/Using_fullscreen_mode\r\n */\r\nexport const enterFullscreen = element => {\r\n\r\n\telement = element || document.documentElement;\r\n\r\n\t// Check which implementation is available\r\n\tlet requestMethod = element.requestFullscreen ||\r\n\t\t\t\t\t\telement.webkitRequestFullscreen ||\r\n\t\t\t\t\t\telement.webkitRequestFullScreen ||\r\n\t\t\t\t\t\telement.mozRequestFullScreen ||\r\n\t\t\t\t\t\telement.msRequestFullscreen;\r\n\r\n\tif( requestMethod ) {\r\n\t\trequestMethod.apply( element );\r\n\t}\r\n\r\n}\r\n\r\n/**\r\n * Creates an HTML element and returns a reference to it.\r\n * If the element already exists the existing instance will\r\n * be returned.\r\n *\r\n * @param {HTMLElement} container\r\n * @param {string} tagname\r\n * @param {string} classname\r\n * @param {string} innerHTML\r\n *\r\n * @return {HTMLElement}\r\n */\r\nexport const createSingletonNode = ( container, tagname, classname, innerHTML='' ) => {\r\n\r\n\t// Find all nodes matching the description\r\n\tlet nodes = container.querySelectorAll( '.' + classname );\r\n\r\n\t// Check all matches to find one which is a direct child of\r\n\t// the specified container\r\n\tfor( let i = 0; i < nodes.length; i++ ) {\r\n\t\tlet testNode = nodes[i];\r\n\t\tif( testNode.parentNode === container ) {\r\n\t\t\treturn testNode;\r\n\t\t}\r\n\t}\r\n\r\n\t// If no node was found, create it now\r\n\tlet node = document.createElement( tagname );\r\n\tnode.className = classname;\r\n\tnode.innerHTML = innerHTML;\r\n\tcontainer.appendChild( node );\r\n\r\n\treturn node;\r\n\r\n}\r\n\r\n/**\r\n * Injects the given CSS styles into the DOM.\r\n *\r\n * @param {string} value\r\n */\r\nexport const createStyleSheet = ( value ) => {\r\n\r\n\tlet tag = document.createElement( 'style' );\r\n\ttag.type = 'text/css';\r\n\r\n\tif( value && value.length > 0 ) {\r\n\t\tif( tag.styleSheet ) {\r\n\t\t\ttag.styleSheet.cssText = value;\r\n\t\t}\r\n\t\telse {\r\n\t\t\ttag.appendChild( document.createTextNode( value ) );\r\n\t\t}\r\n\t}\r\n\r\n\tdocument.head.appendChild( tag );\r\n\r\n\treturn tag;\r\n\r\n}\r\n\r\n/**\r\n * Returns a key:value hash of all query params.\r\n */\r\nexport const getQueryHash = () => {\r\n\r\n\tlet query = {};\r\n\r\n\tlocation.search.replace( /[A-Z0-9]+?=([\\w\\.%-]*)/gi, a => {\r\n\t\tquery[ a.split( '=' ).shift() ] = a.split( '=' ).pop();\r\n\t} );\r\n\r\n\t// Basic deserialization\r\n\tfor( let i in query ) {\r\n\t\tlet value = query[ i ];\r\n\r\n\t\tquery[ i ] = deserialize( unescape( value ) );\r\n\t}\r\n\r\n\t// Do not accept new dependencies via query config to avoid\r\n\t// the potential of malicious script injection\r\n\tif( typeof query['dependencies'] !== 'undefined' ) delete query['dependencies'];\r\n\r\n\treturn query;\r\n\r\n}\r\n\r\n/**\r\n * Returns the remaining height within the parent of the\r\n * target element.\r\n *\r\n * remaining height = [ configured parent height ] - [ current parent height ]\r\n *\r\n * @param {HTMLElement} element\r\n * @param {number} [height]\r\n */\r\nexport const getRemainingHeight = ( element, height = 0 ) => {\r\n\r\n\tif( element ) {\r\n\t\tlet newHeight, oldHeight = element.style.height;\r\n\r\n\t\t// Change the .stretch element height to 0 in order find the height of all\r\n\t\t// the other elements\r\n\t\telement.style.height = '0px';\r\n\r\n\t\t// In Overview mode, the parent (.slide) height is set of 700px.\r\n\t\t// Restore it temporarily to its natural height.\r\n\t\telement.parentNode.style.height = 'auto';\r\n\r\n\t\tnewHeight = height - element.parentNode.offsetHeight;\r\n\r\n\t\t// Restore the old height, just in case\r\n\t\telement.style.height = oldHeight + 'px';\r\n\r\n\t\t// Clear the parent (.slide) height. .removeProperty works in IE9+\r\n\t\telement.parentNode.style.removeProperty('height');\r\n\r\n\t\treturn newHeight;\r\n\t}\r\n\r\n\treturn height;\r\n\r\n}\r\n\r\nconst fileExtensionToMimeMap = {\r\n\t'mp4': 'video/mp4',\r\n\t'm4a': 'video/mp4',\r\n\t'ogv': 'video/ogg',\r\n\t'mpeg': 'video/mpeg',\r\n\t'webm': 'video/webm'\r\n}\r\n\r\n/**\r\n * Guess the MIME type for common file formats.\r\n */\r\nexport const getMimeTypeFromFile = ( filename='' ) => {\r\n\treturn fileExtensionToMimeMap[filename.split('.').pop()]\r\n}\r\n\r\n/**\r\n * Encodes a string for RFC3986-compliant URL format.\r\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#encoding_for_rfc3986\r\n *\r\n * @param {string} url\r\n */\r\nexport const encodeRFC3986URI = ( url='' ) => {\r\n\treturn encodeURI(url)\r\n\t .replace(/%5B/g, \"[\")\r\n\t .replace(/%5D/g, \"]\")\r\n\t .replace(\r\n\t\t/[!'()*]/g,\r\n\t\t(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`\r\n\t );\r\n}","const UA = navigator.userAgent;\r\n\r\nexport const isMobile = /(iphone|ipod|ipad|android)/gi.test( UA ) ||\r\n\t\t\t\t\t\t( navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 ); // iPadOS\r\n\r\nexport const isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA );\r\n\r\nexport const isAndroid = /android/gi.test( UA );","/**\n * fitty v2.4.2 - Snugly resizes text to fit its parent container\n * Copyright (c) 2023 Rik Schennink (https://pqina.nl/)\n */\n\nvar e=function(e){if(e){var t=function(e){return[].slice.call(e)},n=0,i=1,r=2,o=3,a=[],l=null,u=\"requestAnimationFrame\"in e?function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{sync:!1};e.cancelAnimationFrame(l);var n=function(){return s(a.filter((function(e){return e.dirty&&e.active})))};if(t.sync)return n();l=e.requestAnimationFrame(n)}:function(){},c=function(e){return function(t){a.forEach((function(t){return t.dirty=e})),u(t)}},s=function(e){e.filter((function(e){return!e.styleComputed})).forEach((function(e){e.styleComputed=m(e)})),e.filter(y).forEach(v);var t=e.filter(p);t.forEach(d),t.forEach((function(e){v(e),f(e)})),t.forEach(S)},f=function(e){return e.dirty=n},d=function(e){e.availableWidth=e.element.parentNode.clientWidth,e.currentWidth=e.element.scrollWidth,e.previousFontSize=e.currentFontSize,e.currentFontSize=Math.min(Math.max(e.minSize,e.availableWidth/e.currentWidth*e.previousFontSize),e.maxSize),e.whiteSpace=e.multiLine&&e.currentFontSize===e.minSize?\"normal\":\"nowrap\"},p=function(e){return e.dirty!==r||e.dirty===r&&e.element.parentNode.clientWidth!==e.availableWidth},m=function(t){var n=e.getComputedStyle(t.element,null);return t.currentFontSize=parseFloat(n.getPropertyValue(\"font-size\")),t.display=n.getPropertyValue(\"display\"),t.whiteSpace=n.getPropertyValue(\"white-space\"),!0},y=function(e){var t=!1;return!e.preStyleTestCompleted&&(/inline-/.test(e.display)||(t=!0,e.display=\"inline-block\"),\"nowrap\"!==e.whiteSpace&&(t=!0,e.whiteSpace=\"nowrap\"),e.preStyleTestCompleted=!0,t)},v=function(e){e.element.style.whiteSpace=e.whiteSpace,e.element.style.display=e.display,e.element.style.fontSize=e.currentFontSize+\"px\"},S=function(e){e.element.dispatchEvent(new CustomEvent(\"fit\",{detail:{oldValue:e.previousFontSize,newValue:e.currentFontSize,scaleFactor:e.currentFontSize/e.previousFontSize}}))},h=function(e,t){return function(n){e.dirty=t,e.active&&u(n)}},w=function(e){return function(){a=a.filter((function(t){return t.element!==e.element})),e.observeMutations&&e.observer.disconnect(),e.element.style.whiteSpace=e.originalStyle.whiteSpace,e.element.style.display=e.originalStyle.display,e.element.style.fontSize=e.originalStyle.fontSize}},b=function(e){return function(){e.active||(e.active=!0,u())}},z=function(e){return function(){return e.active=!1}},F=function(e){e.observeMutations&&(e.observer=new MutationObserver(h(e,i)),e.observer.observe(e.element,e.observeMutations))},g={minSize:16,maxSize:512,multiLine:!0,observeMutations:\"MutationObserver\"in e&&{subtree:!0,childList:!0,characterData:!0}},W=null,E=function(){e.clearTimeout(W),W=e.setTimeout(c(r),x.observeWindowDelay)},M=[\"resize\",\"orientationchange\"];return Object.defineProperty(x,\"observeWindow\",{set:function(t){var n=\"\".concat(t?\"add\":\"remove\",\"EventListener\");M.forEach((function(t){e[n](t,E)}))}}),x.observeWindow=!0,x.observeWindowDelay=100,x.fitAll=c(o),x}function C(e,t){var n=Object.assign({},g,t),i=e.map((function(e){var t=Object.assign({},n,{element:e,active:!0});return function(e){e.originalStyle={whiteSpace:e.element.style.whiteSpace,display:e.element.style.display,fontSize:e.element.style.fontSize},F(e),e.newbie=!0,e.dirty=!0,a.push(e)}(t),{element:e,fit:h(t,o),unfreeze:b(t),freeze:z(t),unsubscribe:w(t)}}));return u(),i}function x(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return\"string\"==typeof e?C(t(document.querySelectorAll(e)),n):C([e],n)[0]}}(\"undefined\"==typeof window?null:window);export default e;\n","import { extend, queryAll, closest, getMimeTypeFromFile, encodeRFC3986URI } from '../utils/util.js'\r\nimport { isMobile } from '../utils/device.js'\r\n\r\nimport fitty from 'fitty';\r\n\r\n/**\r\n * Handles loading, unloading and playback of slide\r\n * content such as images, videos and iframes.\r\n */\r\nexport default class SlideContent {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.startEmbeddedIframe = this.startEmbeddedIframe.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Should the given element be preloaded?\r\n\t * Decides based on local element attributes and global config.\r\n\t *\r\n\t * @param {HTMLElement} element\r\n\t */\r\n\tshouldPreload( element ) {\r\n\r\n\t\tif( this.Reveal.isScrollView() ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Prefer an explicit global preload setting\r\n\t\tlet preload = this.Reveal.getConfig().preloadIframes;\r\n\r\n\t\t// If no global setting is available, fall back on the element's\r\n\t\t// own preload setting\r\n\t\tif( typeof preload !== 'boolean' ) {\r\n\t\t\tpreload = element.hasAttribute( 'data-preload' );\r\n\t\t}\r\n\r\n\t\treturn preload;\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the given slide is within the configured view\r\n\t * distance. Shows the slide element and loads any content\r\n\t * that is set to load lazily (data-src).\r\n\t *\r\n\t * @param {HTMLElement} slide Slide to show\r\n\t */\r\n\tload( slide, options = {} ) {\r\n\r\n\t\t// Show the slide element\r\n\t\tslide.style.display = this.Reveal.getConfig().display;\r\n\r\n\t\t// Media elements with data-src attributes\r\n\t\tqueryAll( slide, 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ).forEach( element => {\r\n\t\t\tif( element.tagName !== 'IFRAME' || this.shouldPreload( element ) ) {\r\n\t\t\t\telement.setAttribute( 'src', element.getAttribute( 'data-src' ) );\r\n\t\t\t\telement.setAttribute( 'data-lazy-loaded', '' );\r\n\t\t\t\telement.removeAttribute( 'data-src' );\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t// Media elements with children\r\n\t\tqueryAll( slide, 'video, audio' ).forEach( media => {\r\n\t\t\tlet sources = 0;\r\n\r\n\t\t\tqueryAll( media, 'source[data-src]' ).forEach( source => {\r\n\t\t\t\tsource.setAttribute( 'src', source.getAttribute( 'data-src' ) );\r\n\t\t\t\tsource.removeAttribute( 'data-src' );\r\n\t\t\t\tsource.setAttribute( 'data-lazy-loaded', '' );\r\n\t\t\t\tsources += 1;\r\n\t\t\t} );\r\n\r\n\t\t\t// Enable inline video playback in mobile Safari\r\n\t\t\tif( isMobile && media.tagName === 'VIDEO' ) {\r\n\t\t\t\tmedia.setAttribute( 'playsinline', '' );\r\n\t\t\t}\r\n\r\n\t\t\t// If we rewrote sources for this video/audio element, we need\r\n\t\t\t// to manually tell it to load from its new origin\r\n\t\t\tif( sources > 0 ) {\r\n\t\t\t\tmedia.load();\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\r\n\t\t// Show the corresponding background element\r\n\t\tlet background = slide.slideBackgroundElement;\r\n\t\tif( background ) {\r\n\t\t\tbackground.style.display = 'block';\r\n\r\n\t\t\tlet backgroundContent = slide.slideBackgroundContentElement;\r\n\t\t\tlet backgroundIframe = slide.getAttribute( 'data-background-iframe' );\r\n\r\n\t\t\t// If the background contains media, load it\r\n\t\t\tif( background.hasAttribute( 'data-loaded' ) === false ) {\r\n\t\t\t\tbackground.setAttribute( 'data-loaded', 'true' );\r\n\r\n\t\t\t\tlet backgroundImage = slide.getAttribute( 'data-background-image' ),\r\n\t\t\t\t\tbackgroundVideo = slide.getAttribute( 'data-background-video' ),\r\n\t\t\t\t\tbackgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ),\r\n\t\t\t\t\tbackgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' );\r\n\r\n\t\t\t\t// Images\r\n\t\t\t\tif( backgroundImage ) {\r\n\t\t\t\t\t// base64\r\n\t\t\t\t\tif( /^data:/.test( backgroundImage.trim() ) ) {\r\n\t\t\t\t\t\tbackgroundContent.style.backgroundImage = `url(${backgroundImage.trim()})`;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// URL(s)\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tbackgroundContent.style.backgroundImage = backgroundImage.split( ',' ).map( background => {\r\n\t\t\t\t\t\t\t// Decode URL(s) that are already encoded first\r\n\t\t\t\t\t\t\tlet decoded = decodeURI(background.trim());\r\n\t\t\t\t\t\t\treturn `url(${encodeRFC3986URI(decoded)})`;\r\n\t\t\t\t\t\t}).join( ',' );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// Videos\r\n\t\t\t\telse if ( backgroundVideo && !this.Reveal.isSpeakerNotes() ) {\r\n\t\t\t\t\tlet video = document.createElement( 'video' );\r\n\r\n\t\t\t\t\tif( backgroundVideoLoop ) {\r\n\t\t\t\t\t\tvideo.setAttribute( 'loop', '' );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif( backgroundVideoMuted ) {\r\n\t\t\t\t\t\tvideo.muted = true;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Enable inline playback in mobile Safari\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// Mute is required for video to play when using\r\n\t\t\t\t\t// swipe gestures to navigate since they don't\r\n\t\t\t\t\t// count as direct user actions :'(\r\n\t\t\t\t\tif( isMobile ) {\r\n\t\t\t\t\t\tvideo.muted = true;\r\n\t\t\t\t\t\tvideo.setAttribute( 'playsinline', '' );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Support comma separated lists of video sources\r\n\t\t\t\t\tbackgroundVideo.split( ',' ).forEach( source => {\r\n\t\t\t\t\t\tconst sourceElement = document.createElement( 'source' );\r\n\t\t\t\t\t\tsourceElement.setAttribute( 'src', source );\r\n\r\n\t\t\t\t\t\tlet type = getMimeTypeFromFile( source );\r\n\t\t\t\t\t\tif( type ) {\r\n\t\t\t\t\t\t\tsourceElement.setAttribute( 'type', type );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvideo.appendChild( sourceElement );\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\tbackgroundContent.appendChild( video );\r\n\t\t\t\t}\r\n\t\t\t\t// Iframes\r\n\t\t\t\telse if( backgroundIframe && options.excludeIframes !== true ) {\r\n\t\t\t\t\tlet iframe = document.createElement( 'iframe' );\r\n\t\t\t\t\tiframe.setAttribute( 'allowfullscreen', '' );\r\n\t\t\t\t\tiframe.setAttribute( 'mozallowfullscreen', '' );\r\n\t\t\t\t\tiframe.setAttribute( 'webkitallowfullscreen', '' );\r\n\t\t\t\t\tiframe.setAttribute( 'allow', 'autoplay' );\r\n\r\n\t\t\t\t\tiframe.setAttribute( 'data-src', backgroundIframe );\r\n\r\n\t\t\t\t\tiframe.style.width = '100%';\r\n\t\t\t\t\tiframe.style.height = '100%';\r\n\t\t\t\t\tiframe.style.maxHeight = '100%';\r\n\t\t\t\t\tiframe.style.maxWidth = '100%';\r\n\r\n\t\t\t\t\tbackgroundContent.appendChild( iframe );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Start loading preloadable iframes\r\n\t\t\tlet backgroundIframeElement = backgroundContent.querySelector( 'iframe[data-src]' );\r\n\t\t\tif( backgroundIframeElement ) {\r\n\r\n\t\t\t\t// Check if this iframe is eligible to be preloaded\r\n\t\t\t\tif( this.shouldPreload( background ) && !/autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) {\r\n\t\t\t\t\tif( backgroundIframeElement.getAttribute( 'src' ) !== backgroundIframe ) {\r\n\t\t\t\t\t\tbackgroundIframeElement.setAttribute( 'src', backgroundIframe );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.layout( slide );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Applies JS-dependent layout helpers for the scope.\r\n\t */\r\n\tlayout( scopeElement ) {\r\n\r\n\t\t// Autosize text with the r-fit-text class based on the\r\n\t\t// size of its container. This needs to happen after the\r\n\t\t// slide is visible in order to measure the text.\r\n\t\tArray.from( scopeElement.querySelectorAll( '.r-fit-text' ) ).forEach( element => {\r\n\t\t\tfitty( element, {\r\n\t\t\t\tminSize: 24,\r\n\t\t\t\tmaxSize: this.Reveal.getConfig().height * 0.8,\r\n\t\t\t\tobserveMutations: false,\r\n\t\t\t\tobserveWindow: false\r\n\t\t\t} );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Unloads and hides the given slide. This is called when the\r\n\t * slide is moved outside of the configured view distance.\r\n\t *\r\n\t * @param {HTMLElement} slide\r\n\t */\r\n\tunload( slide ) {\r\n\r\n\t\t// Hide the slide element\r\n\t\tslide.style.display = 'none';\r\n\r\n\t\t// Hide the corresponding background element\r\n\t\tlet background = this.Reveal.getSlideBackground( slide );\r\n\t\tif( background ) {\r\n\t\t\tbackground.style.display = 'none';\r\n\r\n\t\t\t// Unload any background iframes\r\n\t\t\tqueryAll( background, 'iframe[src]' ).forEach( element => {\r\n\t\t\t\telement.removeAttribute( 'src' );\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\t\t// Reset lazy-loaded media elements with src attributes\r\n\t\tqueryAll( slide, 'video[data-lazy-loaded][src], audio[data-lazy-loaded][src], iframe[data-lazy-loaded][src]' ).forEach( element => {\r\n\t\t\telement.setAttribute( 'data-src', element.getAttribute( 'src' ) );\r\n\t\t\telement.removeAttribute( 'src' );\r\n\t\t} );\r\n\r\n\t\t// Reset lazy-loaded media elements with children\r\n\t\tqueryAll( slide, 'video[data-lazy-loaded] source[src], audio source[src]' ).forEach( source => {\r\n\t\t\tsource.setAttribute( 'data-src', source.getAttribute( 'src' ) );\r\n\t\t\tsource.removeAttribute( 'src' );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Enforces origin-specific format rules for embedded media.\r\n\t */\r\n\tformatEmbeddedContent() {\r\n\r\n\t\tlet _appendParamToIframeSource = ( sourceAttribute, sourceURL, param ) => {\r\n\t\t\tqueryAll( this.Reveal.getSlidesElement(), 'iframe['+ sourceAttribute +'*=\"'+ sourceURL +'\"]' ).forEach( el => {\r\n\t\t\t\tlet src = el.getAttribute( sourceAttribute );\r\n\t\t\t\tif( src && src.indexOf( param ) === -1 ) {\r\n\t\t\t\t\tel.setAttribute( sourceAttribute, src + ( !/\\?/.test( src ) ? '?' : '&' ) + param );\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t};\r\n\r\n\t\t// YouTube frames must include \"?enablejsapi=1\"\r\n\t\t_appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' );\r\n\t\t_appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' );\r\n\r\n\t\t// Vimeo frames must include \"?api=1\"\r\n\t\t_appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' );\r\n\t\t_appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Start playback of any embedded content inside of\r\n\t * the given element.\r\n\t *\r\n\t * @param {HTMLElement} element\r\n\t */\r\n\tstartEmbeddedContent( element ) {\r\n\r\n\t\tif( element && !this.Reveal.isSpeakerNotes() ) {\r\n\r\n\t\t\t// Restart GIFs\r\n\t\t\tqueryAll( element, 'img[src$=\".gif\"]' ).forEach( el => {\r\n\t\t\t\t// Setting the same unchanged source like this was confirmed\r\n\t\t\t\t// to work in Chrome, FF & Safari\r\n\t\t\t\tel.setAttribute( 'src', el.getAttribute( 'src' ) );\r\n\t\t\t} );\r\n\r\n\t\t\t// HTML5 media elements\r\n\t\t\tqueryAll( element, 'video, audio' ).forEach( el => {\r\n\t\t\t\tif( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Prefer an explicit global autoplay setting\r\n\t\t\t\tlet autoplay = this.Reveal.getConfig().autoPlayMedia;\r\n\r\n\t\t\t\t// If no global setting is available, fall back on the element's\r\n\t\t\t\t// own autoplay setting\r\n\t\t\t\tif( typeof autoplay !== 'boolean' ) {\r\n\t\t\t\t\tautoplay = el.hasAttribute( 'data-autoplay' ) || !!closest( el, '.slide-background' );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( autoplay && typeof el.play === 'function' ) {\r\n\r\n\t\t\t\t\t// If the media is ready, start playback\r\n\t\t\t\t\tif( el.readyState > 1 ) {\r\n\t\t\t\t\t\tthis.startEmbeddedMedia( { target: el } );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Mobile devices never fire a loaded event so instead\r\n\t\t\t\t\t// of waiting, we initiate playback\r\n\t\t\t\t\telse if( isMobile ) {\r\n\t\t\t\t\t\tlet promise = el.play();\r\n\r\n\t\t\t\t\t\t// If autoplay does not work, ensure that the controls are visible so\r\n\t\t\t\t\t\t// that the viewer can start the media on their own\r\n\t\t\t\t\t\tif( promise && typeof promise.catch === 'function' && el.controls === false ) {\r\n\t\t\t\t\t\t\tpromise.catch( () => {\r\n\t\t\t\t\t\t\t\tel.controls = true;\r\n\r\n\t\t\t\t\t\t\t\t// Once the video does start playing, hide the controls again\r\n\t\t\t\t\t\t\t\tel.addEventListener( 'play', () => {\r\n\t\t\t\t\t\t\t\t\tel.controls = false;\r\n\t\t\t\t\t\t\t\t} );\r\n\t\t\t\t\t\t\t} );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// If the media isn't loaded, wait before playing\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tel.removeEventListener( 'loadeddata', this.startEmbeddedMedia ); // remove first to avoid dupes\r\n\t\t\t\t\t\tel.addEventListener( 'loadeddata', this.startEmbeddedMedia );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\t// Normal iframes\r\n\t\t\tqueryAll( element, 'iframe[src]' ).forEach( el => {\r\n\t\t\t\tif( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.startEmbeddedIframe( { target: el } );\r\n\t\t\t} );\r\n\r\n\t\t\t// Lazy loading iframes\r\n\t\t\tqueryAll( element, 'iframe[data-src]' ).forEach( el => {\r\n\t\t\t\tif( closest( el, '.fragment' ) && !closest( el, '.fragment.visible' ) ) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) {\r\n\t\t\t\t\tel.removeEventListener( 'load', this.startEmbeddedIframe ); // remove first to avoid dupes\r\n\t\t\t\t\tel.addEventListener( 'load', this.startEmbeddedIframe );\r\n\t\t\t\t\tel.setAttribute( 'src', el.getAttribute( 'data-src' ) );\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Starts playing an embedded video/audio element after\r\n\t * it has finished loading.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tstartEmbeddedMedia( event ) {\r\n\r\n\t\tlet isAttachedToDOM = !!closest( event.target, 'html' ),\r\n\t\t\tisVisible \t\t= !!closest( event.target, '.present' );\r\n\r\n\t\tif( isAttachedToDOM && isVisible ) {\r\n\t\t\tevent.target.currentTime = 0;\r\n\t\t\tevent.target.play();\r\n\t\t}\r\n\r\n\t\tevent.target.removeEventListener( 'loadeddata', this.startEmbeddedMedia );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * \"Starts\" the content of an embedded iframe using the\r\n\t * postMessage API.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tstartEmbeddedIframe( event ) {\r\n\r\n\t\tlet iframe = event.target;\r\n\r\n\t\tif( iframe && iframe.contentWindow ) {\r\n\r\n\t\t\tlet isAttachedToDOM = !!closest( event.target, 'html' ),\r\n\t\t\t\tisVisible \t\t= !!closest( event.target, '.present' );\r\n\r\n\t\t\tif( isAttachedToDOM && isVisible ) {\r\n\r\n\t\t\t\t// Prefer an explicit global autoplay setting\r\n\t\t\t\tlet autoplay = this.Reveal.getConfig().autoPlayMedia;\r\n\r\n\t\t\t\t// If no global setting is available, fall back on the element's\r\n\t\t\t\t// own autoplay setting\r\n\t\t\t\tif( typeof autoplay !== 'boolean' ) {\r\n\t\t\t\t\tautoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closest( iframe, '.slide-background' );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// YouTube postMessage API\r\n\t\t\t\tif( /youtube\\.com\\/embed\\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {\r\n\t\t\t\t\tiframe.contentWindow.postMessage( '{\"event\":\"command\",\"func\":\"playVideo\",\"args\":\"\"}', '*' );\r\n\t\t\t\t}\r\n\t\t\t\t// Vimeo postMessage API\r\n\t\t\t\telse if( /player\\.vimeo\\.com\\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {\r\n\t\t\t\t\tiframe.contentWindow.postMessage( '{\"method\":\"play\"}', '*' );\r\n\t\t\t\t}\r\n\t\t\t\t// Generic postMessage API\r\n\t\t\t\telse {\r\n\t\t\t\t\tiframe.contentWindow.postMessage( 'slide:start', '*' );\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Stop playback of any embedded content inside of\r\n\t * the targeted slide.\r\n\t *\r\n\t * @param {HTMLElement} element\r\n\t */\r\n\tstopEmbeddedContent( element, options = {} ) {\r\n\r\n\t\toptions = extend( {\r\n\t\t\t// Defaults\r\n\t\t\tunloadIframes: true\r\n\t\t}, options );\r\n\r\n\t\tif( element && element.parentNode ) {\r\n\t\t\t// HTML5 media elements\r\n\t\t\tqueryAll( element, 'video, audio' ).forEach( el => {\r\n\t\t\t\tif( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {\r\n\t\t\t\t\tel.setAttribute('data-paused-by-reveal', '');\r\n\t\t\t\t\tel.pause();\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\t// Generic postMessage API for non-lazy loaded iframes\r\n\t\t\tqueryAll( element, 'iframe' ).forEach( el => {\r\n\t\t\t\tif( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' );\r\n\t\t\t\tel.removeEventListener( 'load', this.startEmbeddedIframe );\r\n\t\t\t});\r\n\r\n\t\t\t// YouTube postMessage API\r\n\t\t\tqueryAll( element, 'iframe[src*=\"youtube.com/embed/\"]' ).forEach( el => {\r\n\t\t\t\tif( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) {\r\n\t\t\t\t\tel.contentWindow.postMessage( '{\"event\":\"command\",\"func\":\"pauseVideo\",\"args\":\"\"}', '*' );\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\t// Vimeo postMessage API\r\n\t\t\tqueryAll( element, 'iframe[src*=\"player.vimeo.com/\"]' ).forEach( el => {\r\n\t\t\t\tif( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) {\r\n\t\t\t\t\tel.contentWindow.postMessage( '{\"method\":\"pause\"}', '*' );\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tif( options.unloadIframes === true ) {\r\n\t\t\t\t// Unload lazy-loaded iframes\r\n\t\t\t\tqueryAll( element, 'iframe[data-src]' ).forEach( el => {\r\n\t\t\t\t\t// Only removing the src doesn't actually unload the frame\r\n\t\t\t\t\t// in all browsers (Firefox) so we set it to blank first\r\n\t\t\t\t\tel.setAttribute( 'src', 'about:blank' );\r\n\t\t\t\t\tel.removeAttribute( 'src' );\r\n\t\t\t\t} );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n","\r\nexport const SLIDES_SELECTOR = '.slides section';\r\nexport const HORIZONTAL_SLIDES_SELECTOR = '.slides>section';\r\nexport const VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section';\r\nexport const HORIZONTAL_BACKGROUNDS_SELECTOR = '.backgrounds>.slide-background';\r\n\r\n// Methods that may not be invoked via the postMessage API\r\nexport const POST_MESSAGE_METHOD_BLACKLIST = /registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/;\r\n\r\n// Regex for retrieving the fragment style from a class attribute\r\nexport const FRAGMENT_STYLE_REGEX = /fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;\r\n\r\n// Slide number formats\r\nexport const SLIDE_NUMBER_FORMAT_HORIZONTAL_DOT_VERTICAL = 'h.v';\r\nexport const SLIDE_NUMBER_FORMAT_HORIZONTAL_SLASH_VERTICAL = 'h/v';\r\nexport const SLIDE_NUMBER_FORMAT_CURRENT = 'c';\r\nexport const SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL = 'c/t';","import {\r\n\tSLIDE_NUMBER_FORMAT_CURRENT,\r\n\tSLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL,\r\n\tSLIDE_NUMBER_FORMAT_HORIZONTAL_DOT_VERTICAL,\r\n\tSLIDE_NUMBER_FORMAT_HORIZONTAL_SLASH_VERTICAL\r\n} from \"../utils/constants\";\r\n\r\n/**\r\n * Handles the display of reveal.js' optional slide number.\r\n */\r\nexport default class SlideNumber {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t}\r\n\r\n\trender() {\r\n\r\n\t\tthis.element = document.createElement( 'div' );\r\n\t\tthis.element.className = 'slide-number';\r\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tlet slideNumberDisplay = 'none';\r\n\t\tif( config.slideNumber && !this.Reveal.isPrintView() ) {\r\n\t\t\tif( config.showSlideNumber === 'all' ) {\r\n\t\t\t\tslideNumberDisplay = 'block';\r\n\t\t\t}\r\n\t\t\telse if( config.showSlideNumber === 'speaker' && this.Reveal.isSpeakerNotes() ) {\r\n\t\t\t\tslideNumberDisplay = 'block';\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.element.style.display = slideNumberDisplay;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the slide number to match the current slide.\r\n\t */\r\n\tupdate() {\r\n\r\n\t\t// Update slide number if enabled\r\n\t\tif( this.Reveal.getConfig().slideNumber && this.element ) {\r\n\t\t\tthis.element.innerHTML = this.getSlideNumber();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the HTML string corresponding to the current slide\r\n\t * number, including formatting.\r\n\t */\r\n\tgetSlideNumber( slide = this.Reveal.getCurrentSlide() ) {\r\n\r\n\t\tlet config = this.Reveal.getConfig();\r\n\t\tlet value;\r\n\t\tlet format = SLIDE_NUMBER_FORMAT_HORIZONTAL_DOT_VERTICAL;\r\n\r\n\t\tif ( typeof config.slideNumber === 'function' ) {\r\n\t\t\tvalue = config.slideNumber( slide );\r\n\t\t} else {\r\n\t\t\t// Check if a custom number format is available\r\n\t\t\tif( typeof config.slideNumber === 'string' ) {\r\n\t\t\t\tformat = config.slideNumber;\r\n\t\t\t}\r\n\r\n\t\t\t// If there are ONLY vertical slides in this deck, always use\r\n\t\t\t// a flattened slide number\r\n\t\t\tif( !/c/.test( format ) && this.Reveal.getHorizontalSlides().length === 1 ) {\r\n\t\t\t\tformat = SLIDE_NUMBER_FORMAT_CURRENT;\r\n\t\t\t}\r\n\r\n\t\t\t// Offset the current slide number by 1 to make it 1-indexed\r\n\t\t\tlet horizontalOffset = slide && slide.dataset.visibility === 'uncounted' ? 0 : 1;\r\n\r\n\t\t\tvalue = [];\r\n\t\t\tswitch( format ) {\r\n\t\t\t\tcase SLIDE_NUMBER_FORMAT_CURRENT:\r\n\t\t\t\t\tvalue.push( this.Reveal.getSlidePastCount( slide ) + horizontalOffset );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL:\r\n\t\t\t\t\tvalue.push( this.Reveal.getSlidePastCount( slide ) + horizontalOffset, '/', this.Reveal.getTotalSlides() );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tlet indices = this.Reveal.getIndices( slide );\r\n\t\t\t\t\tvalue.push( indices.h + horizontalOffset );\r\n\t\t\t\t\tlet sep = format === SLIDE_NUMBER_FORMAT_HORIZONTAL_SLASH_VERTICAL ? '/' : '.';\r\n\t\t\t\t\tif( this.Reveal.isVerticalSlide( slide ) ) value.push( sep, indices.v + 1 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlet url = '#' + this.Reveal.location.getHash( slide );\r\n\t\treturn this.formatNumber( value[0], value[1], value[2], url );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Applies HTML formatting to a slide number before it's\r\n\t * written to the DOM.\r\n\t *\r\n\t * @param {number} a Current slide\r\n\t * @param {string} delimiter Character to separate slide numbers\r\n\t * @param {(number|*)} b Total slides\r\n\t * @param {HTMLElement} [url='#'+locationHash()] The url to link to\r\n\t * @return {string} HTML string fragment\r\n\t */\r\n\tformatNumber( a, delimiter, b, url = '#' + this.Reveal.location.getHash() ) {\r\n\r\n\t\tif( typeof b === 'number' && !isNaN( b ) ) {\r\n\t\t\treturn `\r\n\t\t\t\t\t${a}\r\n\t\t\t\t\t${delimiter}\r\n\t\t\t\t\t${b}\r\n\t\t\t\t\t`;\r\n\t\t}\r\n\t\telse {\r\n\t\t\treturn `\r\n\t\t\t\t\t${a}\r\n\t\t\t\t\t`;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.element.remove();\r\n\r\n\t}\r\n\r\n}","import {\r\n\tSLIDE_NUMBER_FORMAT_CURRENT,\r\n\tSLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL\r\n} from \"../utils/constants\";\r\n\r\n/**\r\n * Makes it possible to jump to a slide by entering its\r\n * slide number or id.\r\n */\r\nexport default class JumpToSlide {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.onInput = this.onInput.bind( this );\r\n\t\tthis.onBlur = this.onBlur.bind( this );\r\n\t\tthis.onKeyDown = this.onKeyDown.bind( this );\r\n\r\n\t}\r\n\r\n\trender() {\r\n\r\n\t\tthis.element = document.createElement( 'div' );\r\n\t\tthis.element.className = 'jump-to-slide';\r\n\r\n this.jumpInput = document.createElement( 'input' );\r\n this.jumpInput.type = 'text';\r\n this.jumpInput.className = 'jump-to-slide-input';\r\n this.jumpInput.placeholder = 'Jump to slide';\r\n\t\tthis.jumpInput.addEventListener( 'input', this.onInput );\r\n\t\tthis.jumpInput.addEventListener( 'keydown', this.onKeyDown );\r\n\t\tthis.jumpInput.addEventListener( 'blur', this.onBlur );\r\n\r\n this.element.appendChild( this.jumpInput );\r\n\r\n\t}\r\n\r\n\tshow() {\r\n\r\n\t\tthis.indicesOnShow = this.Reveal.getIndices();\r\n\r\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\r\n\t\tthis.jumpInput.focus();\r\n\r\n\t}\r\n\r\n\thide() {\r\n\r\n\t\tif( this.isVisible() ) {\r\n\t\t\tthis.element.remove();\r\n\t\t\tthis.jumpInput.value = '';\r\n\r\n\t\t\tclearTimeout( this.jumpTimeout );\r\n\t\t\tdelete this.jumpTimeout;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tisVisible() {\r\n\r\n\t\treturn !!this.element.parentNode;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Parses the current input and jumps to the given slide.\r\n\t */\r\n\tjump() {\r\n\r\n\t\tclearTimeout( this.jumpTimeout );\r\n\t\tdelete this.jumpTimeout;\r\n\r\n\t\tlet query = this.jumpInput.value.trim( '' );\r\n\t\tlet indices;\r\n\r\n\t\t// When slide numbers are formatted to be a single linear mumber\r\n\t\t// (instead of showing a separate horizontal/vertical index) we\r\n\t\t// use the same format for slide jumps\r\n\t\tif( /^\\d+$/.test( query ) ) {\r\n\t\t\tconst slideNumberFormat = this.Reveal.getConfig().slideNumber;\r\n\t\t\tif( slideNumberFormat === SLIDE_NUMBER_FORMAT_CURRENT || slideNumberFormat === SLIDE_NUMBER_FORMAT_CURRENT_SLASH_TOTAL ) {\r\n\t\t\t\tconst slide = this.Reveal.getSlides()[ parseInt( query, 10 ) - 1 ];\r\n\t\t\t\tif( slide ) {\r\n\t\t\t\t\tindices = this.Reveal.getIndices( slide );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( !indices ) {\r\n\t\t\t// If the query uses \"horizontal.vertical\" format, convert to\r\n\t\t\t// \"horizontal/vertical\" so that our URL parser can understand\r\n\t\t\tif( /^\\d+\\.\\d+$/.test( query ) ) {\r\n\t\t\t\tquery = query.replace( '.', '/' );\r\n\t\t\t}\r\n\r\n\t\t\tindices = this.Reveal.location.getIndicesFromHash( query, { oneBasedIndex: true } );\r\n\t\t}\r\n\r\n\t\t// Still no valid index? Fall back on a text search\r\n\t\tif( !indices && /\\S+/i.test( query ) && query.length > 1 ) {\r\n\t\t\tindices = this.search( query );\r\n\t\t}\r\n\r\n\t\tif( indices && query !== '' ) {\r\n\t\t\tthis.Reveal.slide( indices.h, indices.v, indices.f );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tjumpAfter( delay ) {\r\n\r\n\t\tclearTimeout( this.jumpTimeout );\r\n\t\tthis.jumpTimeout = setTimeout( () => this.jump(), delay );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * A lofi search that looks for the given query in all\r\n\t * of our slides and returns the first match.\r\n\t */\r\n\tsearch( query ) {\r\n\r\n\t\tconst regex = new RegExp( '\\\\b' + query.trim() + '\\\\b', 'i' );\r\n\r\n\t\tconst slide = this.Reveal.getSlides().find( ( slide ) => {\r\n\t\t\treturn regex.test( slide.innerText );\r\n\t\t} );\r\n\r\n\t\tif( slide ) {\r\n\t\t\treturn this.Reveal.getIndices( slide );\r\n\t\t}\r\n\t\telse {\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Reverts back to the slide we were on when jump to slide was\r\n\t * invoked.\r\n\t */\r\n\tcancel() {\r\n\r\n\t\tthis.Reveal.slide( this.indicesOnShow.h, this.indicesOnShow.v, this.indicesOnShow.f );\r\n\t\tthis.hide();\r\n\r\n\t}\r\n\r\n\tconfirm() {\r\n\r\n\t\tthis.jump();\r\n\t\tthis.hide();\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.jumpInput.removeEventListener( 'input', this.onInput );\r\n\t\tthis.jumpInput.removeEventListener( 'keydown', this.onKeyDown );\r\n\t\tthis.jumpInput.removeEventListener( 'blur', this.onBlur );\r\n\r\n\t\tthis.element.remove();\r\n\r\n\t}\r\n\r\n\tonKeyDown( event ) {\r\n\r\n\t\tif( event.keyCode === 13 ) {\r\n\t\t\tthis.confirm();\r\n\t\t}\r\n\t\telse if( event.keyCode === 27 ) {\r\n\t\t\tthis.cancel();\r\n\r\n\t\t\tevent.stopImmediatePropagation();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tonInput( event ) {\r\n\r\n\t\tthis.jumpAfter( 200 );\r\n\r\n\t}\r\n\r\n\tonBlur() {\r\n\r\n\t\tsetTimeout( () => this.hide(), 1 );\r\n\r\n\t}\r\n\r\n}","/**\r\n * Converts various color input formats to an {r:0,g:0,b:0} object.\r\n *\r\n * @param {string} color The string representation of a color\r\n * @example\r\n * colorToRgb('#000');\r\n * @example\r\n * colorToRgb('#000000');\r\n * @example\r\n * colorToRgb('rgb(0,0,0)');\r\n * @example\r\n * colorToRgb('rgba(0,0,0)');\r\n *\r\n * @return {{r: number, g: number, b: number, [a]: number}|null}\r\n */\r\nexport const colorToRgb = ( color ) => {\r\n\r\n\tlet hex3 = color.match( /^#([0-9a-f]{3})$/i );\r\n\tif( hex3 && hex3[1] ) {\r\n\t\thex3 = hex3[1];\r\n\t\treturn {\r\n\t\t\tr: parseInt( hex3.charAt( 0 ), 16 ) * 0x11,\r\n\t\t\tg: parseInt( hex3.charAt( 1 ), 16 ) * 0x11,\r\n\t\t\tb: parseInt( hex3.charAt( 2 ), 16 ) * 0x11\r\n\t\t};\r\n\t}\r\n\r\n\tlet hex6 = color.match( /^#([0-9a-f]{6})$/i );\r\n\tif( hex6 && hex6[1] ) {\r\n\t\thex6 = hex6[1];\r\n\t\treturn {\r\n\t\t\tr: parseInt( hex6.slice( 0, 2 ), 16 ),\r\n\t\t\tg: parseInt( hex6.slice( 2, 4 ), 16 ),\r\n\t\t\tb: parseInt( hex6.slice( 4, 6 ), 16 )\r\n\t\t};\r\n\t}\r\n\r\n\tlet rgb = color.match( /^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/i );\r\n\tif( rgb ) {\r\n\t\treturn {\r\n\t\t\tr: parseInt( rgb[1], 10 ),\r\n\t\t\tg: parseInt( rgb[2], 10 ),\r\n\t\t\tb: parseInt( rgb[3], 10 )\r\n\t\t};\r\n\t}\r\n\r\n\tlet rgba = color.match( /^rgba\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\,\\s*([\\d]+|[\\d]*.[\\d]+)\\s*\\)$/i );\r\n\tif( rgba ) {\r\n\t\treturn {\r\n\t\t\tr: parseInt( rgba[1], 10 ),\r\n\t\t\tg: parseInt( rgba[2], 10 ),\r\n\t\t\tb: parseInt( rgba[3], 10 ),\r\n\t\t\ta: parseFloat( rgba[4] )\r\n\t\t};\r\n\t}\r\n\r\n\treturn null;\r\n\r\n}\r\n\r\n/**\r\n * Calculates brightness on a scale of 0-255.\r\n *\r\n * @param {string} color See colorToRgb for supported formats.\r\n * @see {@link colorToRgb}\r\n */\r\nexport const colorBrightness = ( color ) => {\r\n\r\n\tif( typeof color === 'string' ) color = colorToRgb( color );\r\n\r\n\tif( color ) {\r\n\t\treturn ( color.r * 299 + color.g * 587 + color.b * 114 ) / 1000;\r\n\t}\r\n\r\n\treturn null;\r\n\r\n}","import { queryAll } from '../utils/util.js'\r\nimport { colorToRgb, colorBrightness } from '../utils/color.js'\r\n\r\n/**\r\n * Creates and updates slide backgrounds.\r\n */\r\nexport default class Backgrounds {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t}\r\n\r\n\trender() {\r\n\r\n\t\tthis.element = document.createElement( 'div' );\r\n\t\tthis.element.className = 'backgrounds';\r\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Creates the slide background elements and appends them\r\n\t * to the background container. One element is created per\r\n\t * slide no matter if the given slide has visible background.\r\n\t */\r\n\tcreate() {\r\n\r\n\t\t// Clear prior backgrounds\r\n\t\tthis.element.innerHTML = '';\r\n\t\tthis.element.classList.add( 'no-transition' );\r\n\r\n\t\t// Iterate over all horizontal slides\r\n\t\tthis.Reveal.getHorizontalSlides().forEach( slideh => {\r\n\r\n\t\t\tlet backgroundStack = this.createBackground( slideh, this.element );\r\n\r\n\t\t\t// Iterate over all vertical slides\r\n\t\t\tqueryAll( slideh, 'section' ).forEach( slidev => {\r\n\r\n\t\t\t\tthis.createBackground( slidev, backgroundStack );\r\n\r\n\t\t\t\tbackgroundStack.classList.add( 'stack' );\r\n\r\n\t\t\t} );\r\n\r\n\t\t} );\r\n\r\n\t\t// Add parallax background if specified\r\n\t\tif( this.Reveal.getConfig().parallaxBackgroundImage ) {\r\n\r\n\t\t\tthis.element.style.backgroundImage = 'url(\"' + this.Reveal.getConfig().parallaxBackgroundImage + '\")';\r\n\t\t\tthis.element.style.backgroundSize = this.Reveal.getConfig().parallaxBackgroundSize;\r\n\t\t\tthis.element.style.backgroundRepeat = this.Reveal.getConfig().parallaxBackgroundRepeat;\r\n\t\t\tthis.element.style.backgroundPosition = this.Reveal.getConfig().parallaxBackgroundPosition;\r\n\r\n\t\t\t// Make sure the below properties are set on the element - these properties are\r\n\t\t\t// needed for proper transitions to be set on the element via CSS. To remove\r\n\t\t\t// annoying background slide-in effect when the presentation starts, apply\r\n\t\t\t// these properties after short time delay\r\n\t\t\tsetTimeout( () => {\r\n\t\t\t\tthis.Reveal.getRevealElement().classList.add( 'has-parallax-background' );\r\n\t\t\t}, 1 );\r\n\r\n\t\t}\r\n\t\telse {\r\n\r\n\t\t\tthis.element.style.backgroundImage = '';\r\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'has-parallax-background' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Creates a background for the given slide.\r\n\t *\r\n\t * @param {HTMLElement} slide\r\n\t * @param {HTMLElement} container The element that the background\r\n\t * should be appended to\r\n\t * @return {HTMLElement} New background div\r\n\t */\r\n\tcreateBackground( slide, container ) {\r\n\r\n\t\t// Main slide background element\r\n\t\tlet element = document.createElement( 'div' );\r\n\t\telement.className = 'slide-background ' + slide.className.replace( /present|past|future/, '' );\r\n\r\n\t\t// Inner background element that wraps images/videos/iframes\r\n\t\tlet contentElement = document.createElement( 'div' );\r\n\t\tcontentElement.className = 'slide-background-content';\r\n\r\n\t\telement.appendChild( contentElement );\r\n\t\tcontainer.appendChild( element );\r\n\r\n\t\tslide.slideBackgroundElement = element;\r\n\t\tslide.slideBackgroundContentElement = contentElement;\r\n\r\n\t\t// Syncs the background to reflect all current background settings\r\n\t\tthis.sync( slide );\r\n\r\n\t\treturn element;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Renders all of the visual properties of a slide background\r\n\t * based on the various background attributes.\r\n\t *\r\n\t * @param {HTMLElement} slide\r\n\t */\r\n\tsync( slide ) {\r\n\r\n\t\tconst element = slide.slideBackgroundElement,\r\n\t\t\tcontentElement = slide.slideBackgroundContentElement;\r\n\r\n\t\tconst data = {\r\n\t\t\tbackground: slide.getAttribute( 'data-background' ),\r\n\t\t\tbackgroundSize: slide.getAttribute( 'data-background-size' ),\r\n\t\t\tbackgroundImage: slide.getAttribute( 'data-background-image' ),\r\n\t\t\tbackgroundVideo: slide.getAttribute( 'data-background-video' ),\r\n\t\t\tbackgroundIframe: slide.getAttribute( 'data-background-iframe' ),\r\n\t\t\tbackgroundColor: slide.getAttribute( 'data-background-color' ),\r\n\t\t\tbackgroundGradient: slide.getAttribute( 'data-background-gradient' ),\r\n\t\t\tbackgroundRepeat: slide.getAttribute( 'data-background-repeat' ),\r\n\t\t\tbackgroundPosition: slide.getAttribute( 'data-background-position' ),\r\n\t\t\tbackgroundTransition: slide.getAttribute( 'data-background-transition' ),\r\n\t\t\tbackgroundOpacity: slide.getAttribute( 'data-background-opacity' ),\r\n\t\t};\r\n\r\n\t\tconst dataPreload = slide.hasAttribute( 'data-preload' );\r\n\r\n\t\t// Reset the prior background state in case this is not the\r\n\t\t// initial sync\r\n\t\tslide.classList.remove( 'has-dark-background' );\r\n\t\tslide.classList.remove( 'has-light-background' );\r\n\r\n\t\telement.removeAttribute( 'data-loaded' );\r\n\t\telement.removeAttribute( 'data-background-hash' );\r\n\t\telement.removeAttribute( 'data-background-size' );\r\n\t\telement.removeAttribute( 'data-background-transition' );\r\n\t\telement.style.backgroundColor = '';\r\n\r\n\t\tcontentElement.style.backgroundSize = '';\r\n\t\tcontentElement.style.backgroundRepeat = '';\r\n\t\tcontentElement.style.backgroundPosition = '';\r\n\t\tcontentElement.style.backgroundImage = '';\r\n\t\tcontentElement.style.opacity = '';\r\n\t\tcontentElement.innerHTML = '';\r\n\r\n\t\tif( data.background ) {\r\n\t\t\t// Auto-wrap image urls in url(...)\r\n\t\t\tif( /^(http|file|\\/\\/)/gi.test( data.background ) || /\\.(svg|png|jpg|jpeg|gif|bmp|webp)([?#\\s]|$)/gi.test( data.background ) ) {\r\n\t\t\t\tslide.setAttribute( 'data-background-image', data.background );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\telement.style.background = data.background;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Create a hash for this combination of background settings.\r\n\t\t// This is used to determine when two slide backgrounds are\r\n\t\t// the same.\r\n\t\tif( data.background || data.backgroundColor || data.backgroundGradient || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {\r\n\t\t\telement.setAttribute( 'data-background-hash', data.background +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundSize +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundImage +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundVideo +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundIframe +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundColor +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundGradient +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundRepeat +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundPosition +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundTransition +\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata.backgroundOpacity );\r\n\t\t}\r\n\r\n\t\t// Additional and optional background properties\r\n\t\tif( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize );\r\n\t\tif( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;\r\n\t\tif( data.backgroundGradient ) element.style.backgroundImage = data.backgroundGradient;\r\n\t\tif( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );\r\n\r\n\t\tif( dataPreload ) element.setAttribute( 'data-preload', '' );\r\n\r\n\t\t// Background image options are set on the content wrapper\r\n\t\tif( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize;\r\n\t\tif( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat;\r\n\t\tif( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition;\r\n\t\tif( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity;\r\n\r\n\t\tconst contrastClass = this.getContrastClass( slide );\r\n\r\n\t\tif( typeof contrastClass === 'string' ) {\r\n\t\t\tslide.classList.add( contrastClass );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns a class name that can be applied to a slide to indicate\r\n\t * if it has a light or dark background.\r\n\t *\r\n\t * @param {*} slide\r\n\t *\r\n\t * @returns {string|null}\r\n\t */\r\n\tgetContrastClass( slide ) {\r\n\r\n\t\tconst element = slide.slideBackgroundElement;\r\n\r\n\t\t// If this slide has a background color, we add a class that\r\n\t\t// signals if it is light or dark. If the slide has no background\r\n\t\t// color, no class will be added\r\n\t\tlet contrastColor = slide.getAttribute( 'data-background-color' );\r\n\r\n\t\t// If no bg color was found, or it cannot be converted by colorToRgb, check the computed background\r\n\t\tif( !contrastColor || !colorToRgb( contrastColor ) ) {\r\n\t\t\tlet computedBackgroundStyle = window.getComputedStyle( element );\r\n\t\t\tif( computedBackgroundStyle && computedBackgroundStyle.backgroundColor ) {\r\n\t\t\t\tcontrastColor = computedBackgroundStyle.backgroundColor;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( contrastColor ) {\r\n\t\t\tconst rgb = colorToRgb( contrastColor );\r\n\r\n\t\t\t// Ignore fully transparent backgrounds. Some browsers return\r\n\t\t\t// rgba(0,0,0,0) when reading the computed background color of\r\n\t\t\t// an element with no background\r\n\t\t\tif( rgb && rgb.a !== 0 ) {\r\n\t\t\t\tif( colorBrightness( contrastColor ) < 128 ) {\r\n\t\t\t\t\treturn 'has-dark-background';\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\treturn 'has-light-background';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn null;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Bubble the 'has-light-background'/'has-dark-background' classes.\r\n\t */\r\n\tbubbleSlideContrastClassToElement( slide, target ) {\r\n\r\n\t\t[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => {\r\n\t\t\tif( slide.classList.contains( classToBubble ) ) {\r\n\t\t\t\ttarget.classList.add( classToBubble );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\ttarget.classList.remove( classToBubble );\r\n\t\t\t}\r\n\t\t}, this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the background elements to reflect the current\r\n\t * slide.\r\n\t *\r\n\t * @param {boolean} includeAll If true, the backgrounds of\r\n\t * all vertical slides (not just the present) will be updated.\r\n\t */\r\n\tupdate( includeAll = false ) {\r\n\r\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\r\n\t\tlet indices = this.Reveal.getIndices();\r\n\r\n\t\tlet currentBackground = null;\r\n\r\n\t\t// Reverse past/future classes when in RTL mode\r\n\t\tlet horizontalPast = this.Reveal.getConfig().rtl ? 'future' : 'past',\r\n\t\t\thorizontalFuture = this.Reveal.getConfig().rtl ? 'past' : 'future';\r\n\r\n\t\t// Update the classes of all backgrounds to match the\r\n\t\t// states of their slides (past/present/future)\r\n\t\tArray.from( this.element.childNodes ).forEach( ( backgroundh, h ) => {\r\n\r\n\t\t\tbackgroundh.classList.remove( 'past', 'present', 'future' );\r\n\r\n\t\t\tif( h < indices.h ) {\r\n\t\t\t\tbackgroundh.classList.add( horizontalPast );\r\n\t\t\t}\r\n\t\t\telse if ( h > indices.h ) {\r\n\t\t\t\tbackgroundh.classList.add( horizontalFuture );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tbackgroundh.classList.add( 'present' );\r\n\r\n\t\t\t\t// Store a reference to the current background element\r\n\t\t\t\tcurrentBackground = backgroundh;\r\n\t\t\t}\r\n\r\n\t\t\tif( includeAll || h === indices.h ) {\r\n\t\t\t\tqueryAll( backgroundh, '.slide-background' ).forEach( ( backgroundv, v ) => {\r\n\r\n\t\t\t\t\tbackgroundv.classList.remove( 'past', 'present', 'future' );\r\n\r\n\t\t\t\t\tconst indexv = typeof indices.v === 'number' ? indices.v : 0;\r\n\r\n\t\t\t\t\tif( v < indexv ) {\r\n\t\t\t\t\t\tbackgroundv.classList.add( 'past' );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( v > indexv ) {\r\n\t\t\t\t\t\tbackgroundv.classList.add( 'future' );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tbackgroundv.classList.add( 'present' );\r\n\r\n\t\t\t\t\t\t// Only if this is the present horizontal and vertical slide\r\n\t\t\t\t\t\tif( h === indices.h ) currentBackground = backgroundv;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} );\r\n\t\t\t}\r\n\r\n\t\t} );\r\n\r\n\t\t// Stop content inside of previous backgrounds\r\n\t\tif( this.previousBackground ) {\r\n\r\n\t\t\tthis.Reveal.slideContent.stopEmbeddedContent( this.previousBackground, { unloadIframes: !this.Reveal.slideContent.shouldPreload( this.previousBackground ) } );\r\n\r\n\t\t}\r\n\r\n\t\t// Start content in the current background\r\n\t\tif( currentBackground ) {\r\n\r\n\t\t\tthis.Reveal.slideContent.startEmbeddedContent( currentBackground );\r\n\r\n\t\t\tlet currentBackgroundContent = currentBackground.querySelector( '.slide-background-content' );\r\n\t\t\tif( currentBackgroundContent ) {\r\n\r\n\t\t\t\tlet backgroundImageURL = currentBackgroundContent.style.backgroundImage || '';\r\n\r\n\t\t\t\t// Restart GIFs (doesn't work in Firefox)\r\n\t\t\t\tif( /\\.gif/i.test( backgroundImageURL ) ) {\r\n\t\t\t\t\tcurrentBackgroundContent.style.backgroundImage = '';\r\n\t\t\t\t\twindow.getComputedStyle( currentBackgroundContent ).opacity;\r\n\t\t\t\t\tcurrentBackgroundContent.style.backgroundImage = backgroundImageURL;\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Don't transition between identical backgrounds. This\r\n\t\t\t// prevents unwanted flicker.\r\n\t\t\tlet previousBackgroundHash = this.previousBackground ? this.previousBackground.getAttribute( 'data-background-hash' ) : null;\r\n\t\t\tlet currentBackgroundHash = currentBackground.getAttribute( 'data-background-hash' );\r\n\t\t\tif( currentBackgroundHash && currentBackgroundHash === previousBackgroundHash && currentBackground !== this.previousBackground ) {\r\n\t\t\t\tthis.element.classList.add( 'no-transition' );\r\n\t\t\t}\r\n\r\n\t\t\tthis.previousBackground = currentBackground;\r\n\r\n\t\t}\r\n\r\n\t\t// If there's a background brightness flag for this slide,\r\n\t\t// bubble it to the .reveal container\r\n\t\tif( currentSlide ) {\r\n\t\t\tthis.bubbleSlideContrastClassToElement( currentSlide, this.Reveal.getRevealElement() );\r\n\t\t}\r\n\r\n\t\t// Allow the first background to apply without transition\r\n\t\tsetTimeout( () => {\r\n\t\t\tthis.element.classList.remove( 'no-transition' );\r\n\t\t}, 1 );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the position of the parallax background based\r\n\t * on the current slide index.\r\n\t */\r\n\tupdateParallax() {\r\n\r\n\t\tlet indices = this.Reveal.getIndices();\r\n\r\n\t\tif( this.Reveal.getConfig().parallaxBackgroundImage ) {\r\n\r\n\t\t\tlet horizontalSlides = this.Reveal.getHorizontalSlides(),\r\n\t\t\t\tverticalSlides = this.Reveal.getVerticalSlides();\r\n\r\n\t\t\tlet backgroundSize = this.element.style.backgroundSize.split( ' ' ),\r\n\t\t\t\tbackgroundWidth, backgroundHeight;\r\n\r\n\t\t\tif( backgroundSize.length === 1 ) {\r\n\t\t\t\tbackgroundWidth = backgroundHeight = parseInt( backgroundSize[0], 10 );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tbackgroundWidth = parseInt( backgroundSize[0], 10 );\r\n\t\t\t\tbackgroundHeight = parseInt( backgroundSize[1], 10 );\r\n\t\t\t}\r\n\r\n\t\t\tlet slideWidth = this.element.offsetWidth,\r\n\t\t\t\thorizontalSlideCount = horizontalSlides.length,\r\n\t\t\t\thorizontalOffsetMultiplier,\r\n\t\t\t\thorizontalOffset;\r\n\r\n\t\t\tif( typeof this.Reveal.getConfig().parallaxBackgroundHorizontal === 'number' ) {\r\n\t\t\t\thorizontalOffsetMultiplier = this.Reveal.getConfig().parallaxBackgroundHorizontal;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\thorizontalOffsetMultiplier = horizontalSlideCount > 1 ? ( backgroundWidth - slideWidth ) / ( horizontalSlideCount-1 ) : 0;\r\n\t\t\t}\r\n\r\n\t\t\thorizontalOffset = horizontalOffsetMultiplier * indices.h * -1;\r\n\r\n\t\t\tlet slideHeight = this.element.offsetHeight,\r\n\t\t\t\tverticalSlideCount = verticalSlides.length,\r\n\t\t\t\tverticalOffsetMultiplier,\r\n\t\t\t\tverticalOffset;\r\n\r\n\t\t\tif( typeof this.Reveal.getConfig().parallaxBackgroundVertical === 'number' ) {\r\n\t\t\t\tverticalOffsetMultiplier = this.Reveal.getConfig().parallaxBackgroundVertical;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tverticalOffsetMultiplier = ( backgroundHeight - slideHeight ) / ( verticalSlideCount-1 );\r\n\t\t\t}\r\n\r\n\t\t\tverticalOffset = verticalSlideCount > 0 ? verticalOffsetMultiplier * indices.v : 0;\r\n\r\n\t\t\tthis.element.style.backgroundPosition = horizontalOffset + 'px ' + -verticalOffset + 'px';\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.element.remove();\r\n\r\n\t}\r\n\r\n}\r\n","import { queryAll, extend, createStyleSheet, matches, closest } from '../utils/util.js'\r\nimport { FRAGMENT_STYLE_REGEX } from '../utils/constants.js'\r\n\r\n// Counter used to generate unique IDs for auto-animated elements\r\nlet autoAnimateCounter = 0;\r\n\r\n/**\r\n * Automatically animates matching elements across\r\n * slides with the [data-auto-animate] attribute.\r\n */\r\nexport default class AutoAnimate {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Runs an auto-animation between the given slides.\r\n\t *\r\n\t * @param {HTMLElement} fromSlide\r\n\t * @param {HTMLElement} toSlide\r\n\t */\r\n\trun( fromSlide, toSlide ) {\r\n\r\n\t\t// Clean up after prior animations\r\n\t\tthis.reset();\r\n\r\n\t\tlet allSlides = this.Reveal.getSlides();\r\n\t\tlet toSlideIndex = allSlides.indexOf( toSlide );\r\n\t\tlet fromSlideIndex = allSlides.indexOf( fromSlide );\r\n\r\n\t\t// Ensure that both slides are auto-animate targets with the same data-auto-animate-id value\r\n\t\t// (including null if absent on both) and that data-auto-animate-restart isn't set on the\r\n\t\t// physically latter slide (independent of slide direction)\r\n\t\tif( fromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' )\r\n\t\t\t\t&& fromSlide.getAttribute( 'data-auto-animate-id' ) === toSlide.getAttribute( 'data-auto-animate-id' ) \r\n\t\t\t\t&& !( toSlideIndex > fromSlideIndex ? toSlide : fromSlide ).hasAttribute( 'data-auto-animate-restart' ) ) {\r\n\r\n\t\t\t// Create a new auto-animate sheet\r\n\t\t\tthis.autoAnimateStyleSheet = this.autoAnimateStyleSheet || createStyleSheet();\r\n\r\n\t\t\tlet animationOptions = this.getAutoAnimateOptions( toSlide );\r\n\r\n\t\t\t// Set our starting state\r\n\t\t\tfromSlide.dataset.autoAnimate = 'pending';\r\n\t\t\ttoSlide.dataset.autoAnimate = 'pending';\r\n\r\n\t\t\t// Flag the navigation direction, needed for fragment buildup\r\n\t\t\tanimationOptions.slideDirection = toSlideIndex > fromSlideIndex ? 'forward' : 'backward';\r\n\r\n\t\t\t// If the from-slide is hidden because it has moved outside\r\n\t\t\t// the view distance, we need to temporarily show it while\r\n\t\t\t// measuring\r\n\t\t\tlet fromSlideIsHidden = fromSlide.style.display === 'none';\r\n\t\t\tif( fromSlideIsHidden ) fromSlide.style.display = this.Reveal.getConfig().display;\r\n\r\n\t\t\t// Inject our auto-animate styles for this transition\r\n\t\t\tlet css = this.getAutoAnimatableElements( fromSlide, toSlide ).map( elements => {\r\n\t\t\t\treturn this.autoAnimateElements( elements.from, elements.to, elements.options || {}, animationOptions, autoAnimateCounter++ );\r\n\t\t\t} );\r\n\r\n\t\t\tif( fromSlideIsHidden ) fromSlide.style.display = 'none';\r\n\r\n\t\t\t// Animate unmatched elements, if enabled\r\n\t\t\tif( toSlide.dataset.autoAnimateUnmatched !== 'false' && this.Reveal.getConfig().autoAnimateUnmatched === true ) {\r\n\r\n\t\t\t\t// Our default timings for unmatched elements\r\n\t\t\t\tlet defaultUnmatchedDuration = animationOptions.duration * 0.8,\r\n\t\t\t\t\tdefaultUnmatchedDelay = animationOptions.duration * 0.2;\r\n\r\n\t\t\t\tthis.getUnmatchedAutoAnimateElements( toSlide ).forEach( unmatchedElement => {\r\n\r\n\t\t\t\t\tlet unmatchedOptions = this.getAutoAnimateOptions( unmatchedElement, animationOptions );\r\n\t\t\t\t\tlet id = 'unmatched';\r\n\r\n\t\t\t\t\t// If there is a duration or delay set specifically for this\r\n\t\t\t\t\t// element our unmatched elements should adhere to those\r\n\t\t\t\t\tif( unmatchedOptions.duration !== animationOptions.duration || unmatchedOptions.delay !== animationOptions.delay ) {\r\n\t\t\t\t\t\tid = 'unmatched-' + autoAnimateCounter++;\r\n\t\t\t\t\t\tcss.push( `[data-auto-animate=\"running\"] [data-auto-animate-target=\"${id}\"] { transition: opacity ${unmatchedOptions.duration}s ease ${unmatchedOptions.delay}s; }` );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tunmatchedElement.dataset.autoAnimateTarget = id;\r\n\r\n\t\t\t\t}, this );\r\n\r\n\t\t\t\t// Our default transition for unmatched elements\r\n\t\t\t\tcss.push( `[data-auto-animate=\"running\"] [data-auto-animate-target=\"unmatched\"] { transition: opacity ${defaultUnmatchedDuration}s ease ${defaultUnmatchedDelay}s; }` );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Setting the whole chunk of CSS at once is the most\r\n\t\t\t// efficient way to do this. Using sheet.insertRule\r\n\t\t\t// is multiple factors slower.\r\n\t\t\tthis.autoAnimateStyleSheet.innerHTML = css.join( '' );\r\n\r\n\t\t\t// Start the animation next cycle\r\n\t\t\trequestAnimationFrame( () => {\r\n\t\t\t\tif( this.autoAnimateStyleSheet ) {\r\n\t\t\t\t\t// This forces our newly injected styles to be applied in Firefox\r\n\t\t\t\t\tgetComputedStyle( this.autoAnimateStyleSheet ).fontWeight;\r\n\r\n\t\t\t\t\ttoSlide.dataset.autoAnimate = 'running';\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\ttype: 'autoanimate',\r\n\t\t\t\tdata: {\r\n\t\t\t\t\tfromSlide,\r\n\t\t\t\t\ttoSlide,\r\n\t\t\t\t\tsheet: this.autoAnimateStyleSheet\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Rolls back all changes that we've made to the DOM so\r\n\t * that as part of animating.\r\n\t */\r\n\treset() {\r\n\r\n\t\t// Reset slides\r\n\t\tqueryAll( this.Reveal.getRevealElement(), '[data-auto-animate]:not([data-auto-animate=\"\"])' ).forEach( element => {\r\n\t\t\telement.dataset.autoAnimate = '';\r\n\t\t} );\r\n\r\n\t\t// Reset elements\r\n\t\tqueryAll( this.Reveal.getRevealElement(), '[data-auto-animate-target]' ).forEach( element => {\r\n\t\t\tdelete element.dataset.autoAnimateTarget;\r\n\t\t} );\r\n\r\n\t\t// Remove the animation sheet\r\n\t\tif( this.autoAnimateStyleSheet && this.autoAnimateStyleSheet.parentNode ) {\r\n\t\t\tthis.autoAnimateStyleSheet.parentNode.removeChild( this.autoAnimateStyleSheet );\r\n\t\t\tthis.autoAnimateStyleSheet = null;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Creates a FLIP animation where the `to` element starts out\r\n\t * in the `from` element position and animates to its original\r\n\t * state.\r\n\t *\r\n\t * @param {HTMLElement} from\r\n\t * @param {HTMLElement} to\r\n\t * @param {Object} elementOptions Options for this element pair\r\n\t * @param {Object} animationOptions Options set at the slide level\r\n\t * @param {String} id Unique ID that we can use to identify this\r\n\t * auto-animate element in the DOM\r\n\t */\r\n\tautoAnimateElements( from, to, elementOptions, animationOptions, id ) {\r\n\r\n\t\t// 'from' elements are given a data-auto-animate-target with no value,\r\n\t\t// 'to' elements are are given a data-auto-animate-target with an ID\r\n\t\tfrom.dataset.autoAnimateTarget = '';\r\n\t\tto.dataset.autoAnimateTarget = id;\r\n\r\n\t\t// Each element may override any of the auto-animate options\r\n\t\t// like transition easing, duration and delay via data-attributes\r\n\t\tlet options = this.getAutoAnimateOptions( to, animationOptions );\r\n\r\n\t\t// If we're using a custom element matcher the element options\r\n\t\t// may contain additional transition overrides\r\n\t\tif( typeof elementOptions.delay !== 'undefined' ) options.delay = elementOptions.delay;\r\n\t\tif( typeof elementOptions.duration !== 'undefined' ) options.duration = elementOptions.duration;\r\n\t\tif( typeof elementOptions.easing !== 'undefined' ) options.easing = elementOptions.easing;\r\n\r\n\t\tlet fromProps = this.getAutoAnimatableProperties( 'from', from, elementOptions ),\r\n\t\t\ttoProps = this.getAutoAnimatableProperties( 'to', to, elementOptions );\r\n\r\n\t\t// Maintain fragment visibility for matching elements when\r\n\t\t// we're navigating forwards, this way the viewer won't need\r\n\t\t// to step through the same fragments twice\r\n\t\tif( to.classList.contains( 'fragment' ) ) {\r\n\r\n\t\t\t// Don't auto-animate the opacity of fragments to avoid\r\n\t\t\t// conflicts with fragment animations\r\n\t\t\tdelete toProps.styles['opacity'];\r\n\r\n\t\t\tif( from.classList.contains( 'fragment' ) ) {\r\n\r\n\t\t\t\tlet fromFragmentStyle = ( from.className.match( FRAGMENT_STYLE_REGEX ) || [''] )[0];\r\n\t\t\t\tlet toFragmentStyle = ( to.className.match( FRAGMENT_STYLE_REGEX ) || [''] )[0];\r\n\r\n\t\t\t\t// Only skip the fragment if the fragment animation style\r\n\t\t\t\t// remains unchanged\r\n\t\t\t\tif( fromFragmentStyle === toFragmentStyle && animationOptions.slideDirection === 'forward' ) {\r\n\t\t\t\t\tto.classList.add( 'visible', 'disabled' );\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// If translation and/or scaling are enabled, css transform\r\n\t\t// the 'to' element so that it matches the position and size\r\n\t\t// of the 'from' element\r\n\t\tif( elementOptions.translate !== false || elementOptions.scale !== false ) {\r\n\r\n\t\t\tlet presentationScale = this.Reveal.getScale();\r\n\r\n\t\t\tlet delta = {\r\n\t\t\t\tx: ( fromProps.x - toProps.x ) / presentationScale,\r\n\t\t\t\ty: ( fromProps.y - toProps.y ) / presentationScale,\r\n\t\t\t\tscaleX: fromProps.width / toProps.width,\r\n\t\t\t\tscaleY: fromProps.height / toProps.height\r\n\t\t\t};\r\n\r\n\t\t\t// Limit decimal points to avoid 0.0001px blur and stutter\r\n\t\t\tdelta.x = Math.round( delta.x * 1000 ) / 1000;\r\n\t\t\tdelta.y = Math.round( delta.y * 1000 ) / 1000;\r\n\t\t\tdelta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000;\r\n\t\t\tdelta.scaleX = Math.round( delta.scaleX * 1000 ) / 1000;\r\n\r\n\t\t\tlet translate = elementOptions.translate !== false && ( delta.x !== 0 || delta.y !== 0 ),\r\n\t\t\t\tscale = elementOptions.scale !== false && ( delta.scaleX !== 0 || delta.scaleY !== 0 );\r\n\r\n\t\t\t// No need to transform if nothing's changed\r\n\t\t\tif( translate || scale ) {\r\n\r\n\t\t\t\tlet transform = [];\r\n\r\n\t\t\t\tif( translate ) transform.push( `translate(${delta.x}px, ${delta.y}px)` );\r\n\t\t\t\tif( scale ) transform.push( `scale(${delta.scaleX}, ${delta.scaleY})` );\r\n\r\n\t\t\t\tfromProps.styles['transform'] = transform.join( ' ' );\r\n\t\t\t\tfromProps.styles['transform-origin'] = 'top left';\r\n\r\n\t\t\t\ttoProps.styles['transform'] = 'none';\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Delete all unchanged 'to' styles\r\n\t\tfor( let propertyName in toProps.styles ) {\r\n\t\t\tconst toValue = toProps.styles[propertyName];\r\n\t\t\tconst fromValue = fromProps.styles[propertyName];\r\n\r\n\t\t\tif( toValue === fromValue ) {\r\n\t\t\t\tdelete toProps.styles[propertyName];\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\t// If these property values were set via a custom matcher providing\r\n\t\t\t\t// an explicit 'from' and/or 'to' value, we always inject those values.\r\n\t\t\t\tif( toValue.explicitValue === true ) {\r\n\t\t\t\t\ttoProps.styles[propertyName] = toValue.value;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( fromValue.explicitValue === true ) {\r\n\t\t\t\t\tfromProps.styles[propertyName] = fromValue.value;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlet css = '';\r\n\r\n\t\tlet toStyleProperties = Object.keys( toProps.styles );\r\n\r\n\t\t// Only create animate this element IF at least one style\r\n\t\t// property has changed\r\n\t\tif( toStyleProperties.length > 0 ) {\r\n\r\n\t\t\t// Instantly move to the 'from' state\r\n\t\t\tfromProps.styles['transition'] = 'none';\r\n\r\n\t\t\t// Animate towards the 'to' state\r\n\t\t\ttoProps.styles['transition'] = `all ${options.duration}s ${options.easing} ${options.delay}s`;\r\n\t\t\ttoProps.styles['transition-property'] = toStyleProperties.join( ', ' );\r\n\t\t\ttoProps.styles['will-change'] = toStyleProperties.join( ', ' );\r\n\r\n\t\t\t// Build up our custom CSS. We need to override inline styles\r\n\t\t\t// so we need to make our styles vErY IMPORTANT!1!!\r\n\t\t\tlet fromCSS = Object.keys( fromProps.styles ).map( propertyName => {\r\n\t\t\t\treturn propertyName + ': ' + fromProps.styles[propertyName] + ' !important;';\r\n\t\t\t} ).join( '' );\r\n\r\n\t\t\tlet toCSS = Object.keys( toProps.styles ).map( propertyName => {\r\n\t\t\t\treturn propertyName + ': ' + toProps.styles[propertyName] + ' !important;';\r\n\t\t\t} ).join( '' );\r\n\r\n\t\t\tcss = \t'[data-auto-animate-target=\"'+ id +'\"] {'+ fromCSS +'}' +\r\n\t\t\t\t\t'[data-auto-animate=\"running\"] [data-auto-animate-target=\"'+ id +'\"] {'+ toCSS +'}';\r\n\r\n\t\t}\r\n\r\n\t\treturn css;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the auto-animate options for the given element.\r\n\t *\r\n\t * @param {HTMLElement} element Element to pick up options\r\n\t * from, either a slide or an animation target\r\n\t * @param {Object} [inheritedOptions] Optional set of existing\r\n\t * options\r\n\t */\r\n\tgetAutoAnimateOptions( element, inheritedOptions ) {\r\n\r\n\t\tlet options = {\r\n\t\t\teasing: this.Reveal.getConfig().autoAnimateEasing,\r\n\t\t\tduration: this.Reveal.getConfig().autoAnimateDuration,\r\n\t\t\tdelay: 0\r\n\t\t};\r\n\r\n\t\toptions = extend( options, inheritedOptions );\r\n\r\n\t\t// Inherit options from parent elements\r\n\t\tif( element.parentNode ) {\r\n\t\t\tlet autoAnimatedParent = closest( element.parentNode, '[data-auto-animate-target]' );\r\n\t\t\tif( autoAnimatedParent ) {\r\n\t\t\t\toptions = this.getAutoAnimateOptions( autoAnimatedParent, options );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( element.dataset.autoAnimateEasing ) {\r\n\t\t\toptions.easing = element.dataset.autoAnimateEasing;\r\n\t\t}\r\n\r\n\t\tif( element.dataset.autoAnimateDuration ) {\r\n\t\t\toptions.duration = parseFloat( element.dataset.autoAnimateDuration );\r\n\t\t}\r\n\r\n\t\tif( element.dataset.autoAnimateDelay ) {\r\n\t\t\toptions.delay = parseFloat( element.dataset.autoAnimateDelay );\r\n\t\t}\r\n\r\n\t\treturn options;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns an object containing all of the properties\r\n\t * that can be auto-animated for the given element and\r\n\t * their current computed values.\r\n\t *\r\n\t * @param {String} direction 'from' or 'to'\r\n\t */\r\n\tgetAutoAnimatableProperties( direction, element, elementOptions ) {\r\n\r\n\t\tlet config = this.Reveal.getConfig();\r\n\r\n\t\tlet properties = { styles: [] };\r\n\r\n\t\t// Position and size\r\n\t\tif( elementOptions.translate !== false || elementOptions.scale !== false ) {\r\n\t\t\tlet bounds;\r\n\r\n\t\t\t// Custom auto-animate may optionally return a custom tailored\r\n\t\t\t// measurement function\r\n\t\t\tif( typeof elementOptions.measure === 'function' ) {\r\n\t\t\t\tbounds = elementOptions.measure( element );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tif( config.center ) {\r\n\t\t\t\t\t// More precise, but breaks when used in combination\r\n\t\t\t\t\t// with zoom for scaling the deck ¯\\_(ツ)_/¯\r\n\t\t\t\t\tbounds = element.getBoundingClientRect();\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tlet scale = this.Reveal.getScale();\r\n\t\t\t\t\tbounds = {\r\n\t\t\t\t\t\tx: element.offsetLeft * scale,\r\n\t\t\t\t\t\ty: element.offsetTop * scale,\r\n\t\t\t\t\t\twidth: element.offsetWidth * scale,\r\n\t\t\t\t\t\theight: element.offsetHeight * scale\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tproperties.x = bounds.x;\r\n\t\t\tproperties.y = bounds.y;\r\n\t\t\tproperties.width = bounds.width;\r\n\t\t\tproperties.height = bounds.height;\r\n\t\t}\r\n\r\n\t\tconst computedStyles = getComputedStyle( element );\r\n\r\n\t\t// CSS styles\r\n\t\t( elementOptions.styles || config.autoAnimateStyles ).forEach( style => {\r\n\t\t\tlet value;\r\n\r\n\t\t\t// `style` is either the property name directly, or an object\r\n\t\t\t// definition of a style property\r\n\t\t\tif( typeof style === 'string' ) style = { property: style };\r\n\r\n\t\t\tif( typeof style.from !== 'undefined' && direction === 'from' ) {\r\n\t\t\t\tvalue = { value: style.from, explicitValue: true };\r\n\t\t\t}\r\n\t\t\telse if( typeof style.to !== 'undefined' && direction === 'to' ) {\r\n\t\t\t\tvalue = { value: style.to, explicitValue: true };\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\t// Use a unitless value for line-height so that it inherits properly\r\n\t\t\t\tif( style.property === 'line-height' ) {\r\n\t\t\t\t\tvalue = parseFloat( computedStyles['line-height'] ) / parseFloat( computedStyles['font-size'] );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif( isNaN(value) ) {\r\n\t\t\t\t\tvalue = computedStyles[style.property];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif( value !== '' ) {\r\n\t\t\t\tproperties.styles[style.property] = value;\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\treturn properties;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Get a list of all element pairs that we can animate\r\n\t * between the given slides.\r\n\t *\r\n\t * @param {HTMLElement} fromSlide\r\n\t * @param {HTMLElement} toSlide\r\n\t *\r\n\t * @return {Array} Each value is an array where [0] is\r\n\t * the element we're animating from and [1] is the\r\n\t * element we're animating to\r\n\t */\r\n\tgetAutoAnimatableElements( fromSlide, toSlide ) {\r\n\r\n\t\tlet matcher = typeof this.Reveal.getConfig().autoAnimateMatcher === 'function' ? this.Reveal.getConfig().autoAnimateMatcher : this.getAutoAnimatePairs;\r\n\r\n\t\tlet pairs = matcher.call( this, fromSlide, toSlide );\r\n\r\n\t\tlet reserved = [];\r\n\r\n\t\t// Remove duplicate pairs\r\n\t\treturn pairs.filter( ( pair, index ) => {\r\n\t\t\tif( reserved.indexOf( pair.to ) === -1 ) {\r\n\t\t\t\treserved.push( pair.to );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Identifies matching elements between slides.\r\n\t *\r\n\t * You can specify a custom matcher function by using\r\n\t * the `autoAnimateMatcher` config option.\r\n\t */\r\n\tgetAutoAnimatePairs( fromSlide, toSlide ) {\r\n\r\n\t\tlet pairs = [];\r\n\r\n\t\tconst codeNodes = 'pre';\r\n\t\tconst textNodes = 'h1, h2, h3, h4, h5, h6, p, li';\r\n\t\tconst mediaNodes = 'img, video, iframe';\r\n\r\n\t\t// Explicit matches via data-id\r\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, '[data-id]', node => {\r\n\t\t\treturn node.nodeName + ':::' + node.getAttribute( 'data-id' );\r\n\t\t} );\r\n\r\n\t\t// Text\r\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, textNodes, node => {\r\n\t\t\treturn node.nodeName + ':::' + node.innerText;\r\n\t\t} );\r\n\r\n\t\t// Media\r\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, mediaNodes, node => {\r\n\t\t\treturn node.nodeName + ':::' + ( node.getAttribute( 'src' ) || node.getAttribute( 'data-src' ) );\r\n\t\t} );\r\n\r\n\t\t// Code\r\n\t\tthis.findAutoAnimateMatches( pairs, fromSlide, toSlide, codeNodes, node => {\r\n\t\t\treturn node.nodeName + ':::' + node.innerText;\r\n\t\t} );\r\n\r\n\t\tpairs.forEach( pair => {\r\n\t\t\t// Disable scale transformations on text nodes, we transition\r\n\t\t\t// each individual text property instead\r\n\t\t\tif( matches( pair.from, textNodes ) ) {\r\n\t\t\t\tpair.options = { scale: false };\r\n\t\t\t}\r\n\t\t\t// Animate individual lines of code\r\n\t\t\telse if( matches( pair.from, codeNodes ) ) {\r\n\r\n\t\t\t\t// Transition the code block's width and height instead of scaling\r\n\t\t\t\t// to prevent its content from being squished\r\n\t\t\t\tpair.options = { scale: false, styles: [ 'width', 'height' ] };\r\n\r\n\t\t\t\t// Lines of code\r\n\t\t\t\tthis.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-code', node => {\r\n\t\t\t\t\treturn node.textContent;\r\n\t\t\t\t}, {\r\n\t\t\t\t\tscale: false,\r\n\t\t\t\t\tstyles: [],\r\n\t\t\t\t\tmeasure: this.getLocalBoundingBox.bind( this )\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t// Line numbers\r\n\t\t\t\tthis.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-numbers[data-line-number]', node => {\r\n\t\t\t\t\treturn node.getAttribute( 'data-line-number' );\r\n\t\t\t\t}, {\r\n\t\t\t\t\tscale: false,\r\n\t\t\t\t\tstyles: [ 'width' ],\r\n\t\t\t\t\tmeasure: this.getLocalBoundingBox.bind( this )\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t}, this );\r\n\r\n\t\treturn pairs;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Helper method which returns a bounding box based on\r\n\t * the given elements offset coordinates.\r\n\t *\r\n\t * @param {HTMLElement} element\r\n\t * @return {Object} x, y, width, height\r\n\t */\r\n\tgetLocalBoundingBox( element ) {\r\n\r\n\t\tconst presentationScale = this.Reveal.getScale();\r\n\r\n\t\treturn {\r\n\t\t\tx: Math.round( ( element.offsetLeft * presentationScale ) * 100 ) / 100,\r\n\t\t\ty: Math.round( ( element.offsetTop * presentationScale ) * 100 ) / 100,\r\n\t\t\twidth: Math.round( ( element.offsetWidth * presentationScale ) * 100 ) / 100,\r\n\t\t\theight: Math.round( ( element.offsetHeight * presentationScale ) * 100 ) / 100\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Finds matching elements between two slides.\r\n\t *\r\n\t * @param {Array} pairs \tList of pairs to push matches to\r\n\t * @param {HTMLElement} fromScope Scope within the from element exists\r\n\t * @param {HTMLElement} toScope Scope within the to element exists\r\n\t * @param {String} selector CSS selector of the element to match\r\n\t * @param {Function} serializer A function that accepts an element and returns\r\n\t * a stringified ID based on its contents\r\n\t * @param {Object} animationOptions Optional config options for this pair\r\n\t */\r\n\tfindAutoAnimateMatches( pairs, fromScope, toScope, selector, serializer, animationOptions ) {\r\n\r\n\t\tlet fromMatches = {};\r\n\t\tlet toMatches = {};\r\n\r\n\t\t[].slice.call( fromScope.querySelectorAll( selector ) ).forEach( ( element, i ) => {\r\n\t\t\tconst key = serializer( element );\r\n\t\t\tif( typeof key === 'string' && key.length ) {\r\n\t\t\t\tfromMatches[key] = fromMatches[key] || [];\r\n\t\t\t\tfromMatches[key].push( element );\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t[].slice.call( toScope.querySelectorAll( selector ) ).forEach( ( element, i ) => {\r\n\t\t\tconst key = serializer( element );\r\n\t\t\ttoMatches[key] = toMatches[key] || [];\r\n\t\t\ttoMatches[key].push( element );\r\n\r\n\t\t\tlet fromElement;\r\n\r\n\t\t\t// Retrieve the 'from' element\r\n\t\t\tif( fromMatches[key] ) {\r\n\t\t\t\tconst primaryIndex = toMatches[key].length - 1;\r\n\t\t\t\tconst secondaryIndex = fromMatches[key].length - 1;\r\n\r\n\t\t\t\t// If there are multiple identical from elements, retrieve\r\n\t\t\t\t// the one at the same index as our to-element.\r\n\t\t\t\tif( fromMatches[key][ primaryIndex ] ) {\r\n\t\t\t\t\tfromElement = fromMatches[key][ primaryIndex ];\r\n\t\t\t\t\tfromMatches[key][ primaryIndex ] = null;\r\n\t\t\t\t}\r\n\t\t\t\t// If there are no matching from-elements at the same index,\r\n\t\t\t\t// use the last one.\r\n\t\t\t\telse if( fromMatches[key][ secondaryIndex ] ) {\r\n\t\t\t\t\tfromElement = fromMatches[key][ secondaryIndex ];\r\n\t\t\t\t\tfromMatches[key][ secondaryIndex ] = null;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// If we've got a matching pair, push it to the list of pairs\r\n\t\t\tif( fromElement ) {\r\n\t\t\t\tpairs.push({\r\n\t\t\t\t\tfrom: fromElement,\r\n\t\t\t\t\tto: element,\r\n\t\t\t\t\toptions: animationOptions\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns a all elements within the given scope that should\r\n\t * be considered unmatched in an auto-animate transition. If\r\n\t * fading of unmatched elements is turned on, these elements\r\n\t * will fade when going between auto-animate slides.\r\n\t *\r\n\t * Note that parents of auto-animate targets are NOT considered\r\n\t * unmatched since fading them would break the auto-animation.\r\n\t *\r\n\t * @param {HTMLElement} rootElement\r\n\t * @return {Array}\r\n\t */\r\n\tgetUnmatchedAutoAnimateElements( rootElement ) {\r\n\r\n\t\treturn [].slice.call( rootElement.children ).reduce( ( result, element ) => {\r\n\r\n\t\t\tconst containsAnimatedElements = element.querySelector( '[data-auto-animate-target]' );\r\n\r\n\t\t\t// The element is unmatched if\r\n\t\t\t// - It is not an auto-animate target\r\n\t\t\t// - It does not contain any auto-animate targets\r\n\t\t\tif( !element.hasAttribute( 'data-auto-animate-target' ) && !containsAnimatedElements ) {\r\n\t\t\t\tresult.push( element );\r\n\t\t\t}\r\n\r\n\t\t\tif( element.querySelector( '[data-auto-animate-target]' ) ) {\r\n\t\t\t\tresult = result.concat( this.getUnmatchedAutoAnimateElements( element ) );\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}, [] );\r\n\r\n\t}\r\n\r\n}\r\n","import { HORIZONTAL_SLIDES_SELECTOR, HORIZONTAL_BACKGROUNDS_SELECTOR } from '../utils/constants.js'\r\nimport { queryAll } from '../utils/util.js'\r\n\r\nconst HIDE_SCROLLBAR_TIMEOUT = 500;\r\nconst MAX_PROGRESS_SPACING = 4;\r\nconst MIN_PROGRESS_SEGMENT_HEIGHT = 6;\r\nconst MIN_PLAYHEAD_HEIGHT = 8;\r\n\r\n/**\r\n * The scroll view lets you read a reveal.js presentation\r\n * as a linear scrollable page.\r\n */\r\nexport default class ScrollView {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.active = false;\r\n\t\tthis.activatedCallbacks = [];\r\n\r\n\t\tthis.onScroll = this.onScroll.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Activates the scroll view. This rearranges the presentation DOM\r\n\t * by—among other things—wrapping each slide in a page element.\r\n\t */\r\n\tactivate() {\r\n\r\n\t\tif( this.active ) return;\r\n\r\n\t\tconst stateBeforeActivation = this.Reveal.getState();\r\n\r\n\t\tthis.active = true;\r\n\r\n\t\t// Store the full presentation HTML so that we can restore it\r\n\t\t// when/if the scroll view is deactivated\r\n\t\tthis.slideHTMLBeforeActivation = this.Reveal.getSlidesElement().innerHTML;\r\n\r\n\t\tconst horizontalSlides = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_SLIDES_SELECTOR );\r\n\t\tconst horizontalBackgrounds = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_BACKGROUNDS_SELECTOR );\r\n\r\n\t\tthis.viewportElement.classList.add( 'loading-scroll-mode', 'reveal-scroll' );\r\n\r\n\t\tlet presentationBackground;\r\n\r\n\t\tconst viewportStyles = window.getComputedStyle( this.viewportElement );\r\n\t\tif( viewportStyles && viewportStyles.background ) {\r\n\t\t\tpresentationBackground = viewportStyles.background;\r\n\t\t}\r\n\r\n\t\tconst pageElements = [];\r\n\t\tconst pageContainer = horizontalSlides[0].parentNode;\r\n\r\n\t\tlet previousSlide;\r\n\r\n\t\t// Creates a new page element and appends the given slide/bg\r\n\t\t// to it.\r\n\t\tconst createPageElement = ( slide, h, v, isVertical ) => {\r\n\r\n\t\t\tlet contentContainer;\r\n\r\n\t\t\t// If this slide is part of an auto-animation sequence, we\r\n\t\t\t// group it under the same page element as the previous slide\r\n\t\t\tif( previousSlide && this.Reveal.shouldAutoAnimateBetween( previousSlide, slide ) ) {\r\n\t\t\t\tcontentContainer = document.createElement( 'div' );\r\n\t\t\t\tcontentContainer.className = 'scroll-page-content scroll-auto-animate-page';\r\n\t\t\t\tcontentContainer.style.display = 'none';\r\n\t\t\t\tpreviousSlide.closest( '.scroll-page-content' ).parentNode.appendChild( contentContainer );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\t// Wrap the slide in a page element and hide its overflow\r\n\t\t\t\t// so that no page ever flows onto another\r\n\t\t\t\tconst page = document.createElement( 'div' );\r\n\t\t\t\tpage.className = 'scroll-page';\r\n\t\t\t\tpageElements.push( page );\r\n\r\n\t\t\t\t// This transfers over the background of the vertical stack containing\r\n\t\t\t\t// the slide if it exists. Otherwise, it uses the presentation-wide\r\n\t\t\t\t// background.\r\n\t\t\t\tif( isVertical && horizontalBackgrounds.length > h ) {\r\n\t\t\t\t\tconst slideBackground = horizontalBackgrounds[h];\r\n\t\t\t\t\tconst pageBackground = window.getComputedStyle( slideBackground );\r\n\r\n\t\t\t\t\tif( pageBackground && pageBackground.background ) {\r\n\t\t\t\t\t\tpage.style.background = pageBackground.background;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( presentationBackground ) {\r\n\t\t\t\t\t\tpage.style.background = presentationBackground;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if( presentationBackground ) {\r\n\t\t\t\t\tpage.style.background = presentationBackground;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst stickyContainer = document.createElement( 'div' );\r\n\t\t\t\tstickyContainer.className = 'scroll-page-sticky';\r\n\t\t\t\tpage.appendChild( stickyContainer );\r\n\r\n\t\t\t\tcontentContainer = document.createElement( 'div' );\r\n\t\t\t\tcontentContainer.className = 'scroll-page-content';\r\n\t\t\t\tstickyContainer.appendChild( contentContainer );\r\n\t\t\t}\r\n\r\n\t\t\tcontentContainer.appendChild( slide );\r\n\r\n\t\t\tslide.classList.remove( 'past', 'future' );\r\n\t\t\tslide.setAttribute( 'data-index-h', h );\r\n\t\t\tslide.setAttribute( 'data-index-v', v );\r\n\r\n\t\t\tif( slide.slideBackgroundElement ) {\r\n\t\t\t\tslide.slideBackgroundElement.remove( 'past', 'future' );\r\n\t\t\t\tcontentContainer.insertBefore( slide.slideBackgroundElement, slide );\r\n\t\t\t}\r\n\r\n\t\t\tpreviousSlide = slide;\r\n\r\n\t\t}\r\n\r\n\t\t// Slide and slide background layout\r\n\t\thorizontalSlides.forEach( ( horizontalSlide, h ) => {\r\n\r\n\t\t\tif( this.Reveal.isVerticalStack( horizontalSlide ) ) {\r\n\t\t\t\thorizontalSlide.querySelectorAll( 'section' ).forEach( ( verticalSlide, v ) => {\r\n\t\t\t\t\tcreatePageElement( verticalSlide, h, v, true );\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tcreatePageElement( horizontalSlide, h, 0 );\r\n\t\t\t}\r\n\r\n\t\t}, this );\r\n\r\n\t\tthis.createProgressBar();\r\n\r\n\t\t// Remove leftover stacks\r\n\t\tqueryAll( this.Reveal.getRevealElement(), '.stack' ).forEach( stack => stack.remove() );\r\n\r\n\t\t// Add our newly created pages to the DOM\r\n\t\tpageElements.forEach( page => pageContainer.appendChild( page ) );\r\n\r\n\t\t// Re-run JS-based content layout after the slide is added to page DOM\r\n\t\tthis.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );\r\n\r\n\t\tthis.Reveal.layout();\r\n\t\tthis.Reveal.setState( stateBeforeActivation );\r\n\r\n\t\tthis.activatedCallbacks.forEach( callback => callback() );\r\n\t\tthis.activatedCallbacks = [];\r\n\r\n\t\tthis.restoreScrollPosition();\r\n\r\n\t\tthis.viewportElement.classList.remove( 'loading-scroll-mode' );\r\n\t\tthis.viewportElement.addEventListener( 'scroll', this.onScroll, { passive: true } );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Deactivates the scroll view and restores the standard slide-based\r\n\t * presentation.\r\n\t */\r\n\tdeactivate() {\r\n\r\n\t\tif( !this.active ) return;\r\n\r\n\t\tconst stateBeforeDeactivation = this.Reveal.getState();\r\n\r\n\t\tthis.active = false;\r\n\r\n\t\tthis.viewportElement.removeEventListener( 'scroll', this.onScroll );\r\n\t\tthis.viewportElement.classList.remove( 'reveal-scroll' );\r\n\r\n\t\tthis.removeProgressBar();\r\n\r\n\t\tthis.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation;\r\n\t\tthis.Reveal.sync();\r\n\t\tthis.Reveal.setState( stateBeforeDeactivation );\r\n\r\n\t\tthis.slideHTMLBeforeActivation = null;\r\n\r\n\t}\r\n\r\n\ttoggle( override ) {\r\n\r\n\t\tif( typeof override === 'boolean' ) {\r\n\t\t\toverride ? this.activate() : this.deactivate();\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.isActive() ? this.deactivate() : this.activate();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if the scroll view is currently active.\r\n\t */\r\n\tisActive() {\r\n\r\n\t\treturn this.active;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Renders the progress bar component.\r\n\t */\r\n\tcreateProgressBar() {\r\n\r\n\t\tthis.progressBar = document.createElement( 'div' );\r\n\t\tthis.progressBar.className = 'scrollbar';\r\n\r\n\t\tthis.progressBarInner = document.createElement( 'div' );\r\n\t\tthis.progressBarInner.className = 'scrollbar-inner';\r\n\t\tthis.progressBar.appendChild( this.progressBarInner );\r\n\r\n\t\tthis.progressBarPlayhead = document.createElement( 'div' );\r\n\t\tthis.progressBarPlayhead.className = 'scrollbar-playhead';\r\n\t\tthis.progressBarInner.appendChild( this.progressBarPlayhead );\r\n\r\n\t\tthis.viewportElement.insertBefore( this.progressBar, this.viewportElement.firstChild );\r\n\r\n\t\tconst handleDocumentMouseMove\t= ( event ) => {\r\n\r\n\t\t\tlet progress = ( event.clientY - this.progressBarInner.getBoundingClientRect().top ) / this.progressBarHeight;\r\n\t\t\tprogress = Math.max( Math.min( progress, 1 ), 0 );\r\n\r\n\t\t\tthis.viewportElement.scrollTop = progress * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );\r\n\r\n\t\t};\r\n\r\n\t\tconst handleDocumentMouseUp = ( event ) => {\r\n\r\n\t\t\tthis.draggingProgressBar = false;\r\n\t\t\tthis.showProgressBar();\r\n\r\n\t\t\tdocument.removeEventListener( 'mousemove', handleDocumentMouseMove );\r\n\t\t\tdocument.removeEventListener( 'mouseup', handleDocumentMouseUp );\r\n\r\n\t\t};\r\n\r\n\t\tconst handleMouseDown = ( event ) => {\r\n\r\n\t\t\tevent.preventDefault();\r\n\r\n\t\t\tthis.draggingProgressBar = true;\r\n\r\n\t\t\tdocument.addEventListener( 'mousemove', handleDocumentMouseMove );\r\n\t\t\tdocument.addEventListener( 'mouseup', handleDocumentMouseUp );\r\n\r\n\t\t\thandleDocumentMouseMove( event );\r\n\r\n\t\t};\r\n\r\n\t\tthis.progressBarInner.addEventListener( 'mousedown', handleMouseDown );\r\n\r\n\t}\r\n\r\n\tremoveProgressBar() {\r\n\r\n\t\tif( this.progressBar ) {\r\n\t\t\tthis.progressBar.remove();\r\n\t\t\tthis.progressBar = null;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tlayout() {\r\n\r\n\t\tif( this.isActive() ) {\r\n\t\t\tthis.syncPages();\r\n\t\t\tthis.syncScrollPosition();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates our pages to match the latest configuration and\r\n\t * presentation size.\r\n\t */\r\n\tsyncPages() {\r\n\r\n\t\tconst config = this.Reveal.getConfig();\r\n\r\n\t\tconst slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );\r\n\t\tconst scale = this.Reveal.getScale();\r\n\t\tconst useCompactLayout = config.scrollLayout === 'compact';\r\n\r\n\t\tconst viewportHeight = this.viewportElement.offsetHeight;\r\n\t\tconst compactHeight = slideSize.height * scale;\r\n\t\tconst pageHeight = useCompactLayout ? compactHeight : viewportHeight;\r\n\r\n\t\t// The height that needs to be scrolled between scroll triggers\r\n\t\tthis.scrollTriggerHeight = useCompactLayout ? compactHeight : viewportHeight;\r\n\r\n\t\tthis.viewportElement.style.setProperty( '--page-height', pageHeight + 'px' );\r\n\t\tthis.viewportElement.style.scrollSnapType = typeof config.scrollSnap === 'string' ? `y ${config.scrollSnap}` : '';\r\n\r\n\t\t// This will hold all scroll triggers used to show/hide slides\r\n\t\tthis.slideTriggers = [];\r\n\r\n\t\tconst pageElements = Array.from( this.Reveal.getRevealElement().querySelectorAll( '.scroll-page' ) );\r\n\r\n\t\tthis.pages = pageElements.map( pageElement => {\r\n\t\t\tconst page = this.createPage({\r\n\t\t\t\tpageElement,\r\n\t\t\t\tslideElement: pageElement.querySelector( 'section' ),\r\n\t\t\t\tstickyElement: pageElement.querySelector( '.scroll-page-sticky' ),\r\n\t\t\t\tcontentElement: pageElement.querySelector( '.scroll-page-content' ),\r\n\t\t\t\tbackgroundElement: pageElement.querySelector( '.slide-background' ),\r\n\t\t\t\tautoAnimateElements: pageElement.querySelectorAll( '.scroll-auto-animate-page' ),\r\n\t\t\t\tautoAnimatePages: []\r\n\t\t\t});\r\n\r\n\t\t\tpage.pageElement.style.setProperty( '--slide-height', config.center === true ? 'auto' : slideSize.height + 'px' );\r\n\r\n\t\t\tthis.slideTriggers.push({\r\n\t\t\t\tpage: page,\r\n\t\t\t\tactivate: () => this.activatePage( page ),\r\n\t\t\t\tdeactivate: () => this.deactivatePage( page )\r\n\t\t\t});\r\n\r\n\t\t\t// Create scroll triggers that show/hide fragments\r\n\t\t\tthis.createFragmentTriggersForPage( page );\r\n\r\n\t\t\t// Create scroll triggers for triggering auto-animate steps\r\n\t\t\tif( page.autoAnimateElements.length > 0 ) {\r\n\t\t\t\tthis.createAutoAnimateTriggersForPage( page );\r\n\t\t\t}\r\n\r\n\t\t\tlet totalScrollTriggerCount = Math.max( page.scrollTriggers.length - 1, 0 );\r\n\r\n\t\t\t// Each auto-animate step may include its own scroll triggers\r\n\t\t\t// for fragments, ensure we count those as well\r\n\t\t\ttotalScrollTriggerCount += page.autoAnimatePages.reduce( ( total, page ) => {\r\n\t\t\t\treturn total + Math.max( page.scrollTriggers.length - 1, 0 );\r\n\t\t\t}, page.autoAnimatePages.length );\r\n\r\n\t\t\t// Clean up from previous renders\r\n\t\t\tpage.pageElement.querySelectorAll( '.scroll-snap-point' ).forEach( el => el.remove() );\r\n\r\n\t\t\t// Create snap points for all scroll triggers\r\n\t\t\t// - Can't be absolute in FF\r\n\t\t\t// - Can't be 0-height in Safari\r\n\t\t\t// - Can't use snap-align on parent in Safari because then\r\n\t\t\t// inner triggers won't work\r\n\t\t\tfor( let i = 0; i < totalScrollTriggerCount + 1; i++ ) {\r\n\t\t\t\tconst triggerStick = document.createElement( 'div' );\r\n\t\t\t\ttriggerStick.className = 'scroll-snap-point';\r\n\t\t\t\ttriggerStick.style.height = this.scrollTriggerHeight + 'px';\r\n\t\t\t\ttriggerStick.style.scrollSnapAlign = useCompactLayout ? 'center' : 'start';\r\n\t\t\t\tpage.pageElement.appendChild( triggerStick );\r\n\r\n\t\t\t\tif( i === 0 ) {\r\n\t\t\t\t\ttriggerStick.style.marginTop = -this.scrollTriggerHeight + 'px';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// In the compact layout, only slides with scroll triggers cover the\r\n\t\t\t// full viewport height. This helps avoid empty gaps before or after\r\n\t\t\t// a sticky slide.\r\n\t\t\tif( useCompactLayout && page.scrollTriggers.length > 0 ) {\r\n\t\t\t\tpage.pageHeight = viewportHeight;\r\n\t\t\t\tpage.pageElement.style.setProperty( '--page-height', viewportHeight + 'px' );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tpage.pageHeight = pageHeight;\r\n\t\t\t\tpage.pageElement.style.removeProperty( '--page-height' );\r\n\t\t\t}\r\n\r\n\t\t\t// Add scroll padding based on how many scroll triggers we have\r\n\t\t\tpage.scrollPadding = this.scrollTriggerHeight * totalScrollTriggerCount;\r\n\r\n\t\t\t// The total height including scrollable space\r\n\t\t\tpage.totalHeight = page.pageHeight + page.scrollPadding;\r\n\r\n\t\t\t// This is used to pad the height of our page in CSS\r\n\t\t\tpage.pageElement.style.setProperty( '--page-scroll-padding', page.scrollPadding + 'px' );\r\n\r\n\t\t\t// If this is a sticky page, stick it to the vertical center\r\n\t\t\tif( totalScrollTriggerCount > 0 ) {\r\n\t\t\t\tpage.stickyElement.style.position = 'sticky';\r\n\t\t\t\tpage.stickyElement.style.top = Math.max( ( viewportHeight - page.pageHeight ) / 2, 0 ) + 'px';\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tpage.stickyElement.style.position = 'relative';\r\n\t\t\t\tpage.pageElement.style.scrollSnapAlign = page.pageHeight < viewportHeight ? 'center' : 'start';\r\n\t\t\t}\r\n\r\n\t\t\treturn page;\r\n\t\t} );\r\n\r\n\t\tthis.setTriggerRanges();\r\n\r\n\t\t/*\r\n\t\tconsole.log(this.slideTriggers.map( t => {\r\n\t\t\treturn {\r\n\t\t\t\trange: `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`,\r\n\t\t\t\ttriggers: t.page.scrollTriggers.map( t => {\r\n\t\t\t\t\treturn `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`\r\n\t\t\t\t}).join( ', ' ),\r\n\t\t\t}\r\n\t\t}))\r\n\t\t*/\r\n\r\n\t\tthis.viewportElement.setAttribute( 'data-scrollbar', config.scrollProgress );\r\n\r\n\t\tif( config.scrollProgress && this.totalScrollTriggerCount > 1 ) {\r\n\t\t\t// Create the progress bar if it doesn't already exist\r\n\t\t\tif( !this.progressBar ) this.createProgressBar();\r\n\r\n\t\t\tthis.syncProgressBar();\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.removeProgressBar();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Calculates and sets the scroll range for all of our scroll\r\n\t * triggers.\r\n\t */\r\n\tsetTriggerRanges() {\r\n\r\n\t\t// Calculate the total number of scroll triggers\r\n\t\tthis.totalScrollTriggerCount = this.slideTriggers.reduce( ( total, trigger ) => {\r\n\t\t\treturn total + Math.max( trigger.page.scrollTriggers.length, 1 );\r\n\t\t}, 0 );\r\n\r\n\t\tlet rangeStart = 0;\r\n\r\n\t\t// Calculate the scroll range of each scroll trigger on a scale\r\n\t\t// of 0-1\r\n\t\tthis.slideTriggers.forEach( ( trigger, i ) => {\r\n\t\t\ttrigger.range = [\r\n\t\t\t\trangeStart,\r\n\t\t\t\trangeStart + Math.max( trigger.page.scrollTriggers.length, 1 ) / this.totalScrollTriggerCount\r\n\t\t\t];\r\n\r\n\t\t\tconst scrollTriggerSegmentSize = ( trigger.range[1] - trigger.range[0] ) / trigger.page.scrollTriggers.length;\r\n\t\t\t// Set the range for each inner scroll trigger\r\n\t\t\ttrigger.page.scrollTriggers.forEach( ( scrollTrigger, i ) => {\r\n\t\t\t\tscrollTrigger.range = [\r\n\t\t\t\t\trangeStart + i * scrollTriggerSegmentSize,\r\n\t\t\t\t\trangeStart + ( i + 1 ) * scrollTriggerSegmentSize\r\n\t\t\t\t];\r\n\t\t\t} );\r\n\r\n\t\t\trangeStart = trigger.range[1];\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Creates one scroll trigger for each fragments in the given page.\r\n\t *\r\n\t * @param {*} page\r\n\t */\r\n\tcreateFragmentTriggersForPage( page, slideElement ) {\r\n\r\n\t\tslideElement = slideElement || page.slideElement;\r\n\r\n\t\t// Each fragment 'group' is an array containing one or more\r\n\t\t// fragments. Multiple fragments that appear at the same time\r\n\t\t// are part of the same group.\r\n\t\tconst fragmentGroups = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment' ), true );\r\n\r\n\t\t// Create scroll triggers that show/hide fragments\r\n\t\tif( fragmentGroups.length ) {\r\n\t\t\tpage.fragments = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment:not(.disabled)' ) );\r\n\t\t\tpage.scrollTriggers.push(\r\n\t\t\t\t// Trigger for the initial state with no fragments visible\r\n\t\t\t\t{\r\n\t\t\t\t\tactivate: () => {\r\n\t\t\t\t\t\tthis.Reveal.fragments.update( -1, page.fragments, slideElement );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t);\r\n\r\n\t\t\t// Triggers for each fragment group\r\n\t\t\tfragmentGroups.forEach( ( fragments, i ) => {\r\n\t\t\t\tpage.scrollTriggers.push({\r\n\t\t\t\t\tactivate: () => {\r\n\t\t\t\t\t\tthis.Reveal.fragments.update( i, page.fragments, slideElement );\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\r\n\t\treturn page.scrollTriggers.length;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Creates scroll triggers for the auto-animate steps in the\r\n\t * given page.\r\n\t *\r\n\t * @param {*} page\r\n\t */\r\n\tcreateAutoAnimateTriggersForPage( page ) {\r\n\r\n\t\tif( page.autoAnimateElements.length > 0 ) {\r\n\r\n\t\t\t// Triggers for each subsequent auto-animate slide\r\n\t\t\tthis.slideTriggers.push( ...Array.from( page.autoAnimateElements ).map( ( autoAnimateElement, i ) => {\r\n\t\t\t\tlet autoAnimatePage = this.createPage({\r\n\t\t\t\t\tslideElement: autoAnimateElement.querySelector( 'section' ),\r\n\t\t\t\t\tcontentElement: autoAnimateElement,\r\n\t\t\t\t\tbackgroundElement: autoAnimateElement.querySelector( '.slide-background' )\r\n\t\t\t\t});\r\n\r\n\t\t\t\t// Create fragment scroll triggers for the auto-animate slide\r\n\t\t\t\tthis.createFragmentTriggersForPage( autoAnimatePage, autoAnimatePage.slideElement );\r\n\r\n\t\t\t\tpage.autoAnimatePages.push( autoAnimatePage );\r\n\r\n\t\t\t\t// Return our slide trigger\r\n\t\t\t\treturn {\r\n\t\t\t\t\tpage: autoAnimatePage,\r\n\t\t\t\t\tactivate: () => this.activatePage( autoAnimatePage ),\r\n\t\t\t\t\tdeactivate: () => this.deactivatePage( autoAnimatePage )\r\n\t\t\t\t};\r\n\t\t\t}));\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Helper method for creating a page definition and adding\r\n\t * required fields. A \"page\" is a slide or auto-animate step.\r\n\t */\r\n\tcreatePage( page ) {\r\n\r\n\t\tpage.scrollTriggers = [];\r\n\t\tpage.indexh = parseInt( page.slideElement.getAttribute( 'data-index-h' ), 10 );\r\n\t\tpage.indexv = parseInt( page.slideElement.getAttribute( 'data-index-v' ), 10 );\r\n\r\n\t\treturn page;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Rerenders progress bar segments so that they match the current\r\n\t * reveal.js config and size.\r\n\t */\r\n\tsyncProgressBar() {\r\n\r\n\t\tthis.progressBarInner.querySelectorAll( '.scrollbar-slide' ).forEach( slide => slide.remove() );\r\n\r\n\t\tconst scrollHeight = this.viewportElement.scrollHeight;\r\n\t\tconst viewportHeight = this.viewportElement.offsetHeight;\r\n\t\tconst viewportHeightFactor = viewportHeight / scrollHeight;\r\n\r\n\t\tthis.progressBarHeight = this.progressBarInner.offsetHeight;\r\n\t\tthis.playheadHeight = Math.max( viewportHeightFactor * this.progressBarHeight, MIN_PLAYHEAD_HEIGHT );\r\n\t\tthis.progressBarScrollableHeight = this.progressBarHeight - this.playheadHeight;\r\n\r\n\t\tconst progressSegmentHeight = viewportHeight / scrollHeight * this.progressBarHeight;\r\n\t\tconst spacing = Math.min( progressSegmentHeight / 8, MAX_PROGRESS_SPACING );\r\n\r\n\t\tthis.progressBarPlayhead.style.height = this.playheadHeight - spacing + 'px';\r\n\r\n\t\t// Don't show individual segments if they're too small\r\n\t\tif( progressSegmentHeight > MIN_PROGRESS_SEGMENT_HEIGHT ) {\r\n\r\n\t\t\tthis.slideTriggers.forEach( slideTrigger => {\r\n\r\n\t\t\t\tconst { page } = slideTrigger;\r\n\r\n\t\t\t\t// Visual representation of a slide\r\n\t\t\t\tpage.progressBarSlide = document.createElement( 'div' );\r\n\t\t\t\tpage.progressBarSlide.className = 'scrollbar-slide';\r\n\t\t\t\tpage.progressBarSlide.style.top = slideTrigger.range[0] * this.progressBarHeight + 'px';\r\n\t\t\t\tpage.progressBarSlide.style.height = ( slideTrigger.range[1] - slideTrigger.range[0] ) * this.progressBarHeight - spacing + 'px';\r\n\t\t\t\tpage.progressBarSlide.classList.toggle( 'has-triggers', page.scrollTriggers.length > 0 );\r\n\t\t\t\tthis.progressBarInner.appendChild( page.progressBarSlide );\r\n\r\n\t\t\t\t// Visual representations of each scroll trigger\r\n\t\t\t\tpage.scrollTriggerElements = page.scrollTriggers.map( ( trigger, i ) => {\r\n\r\n\t\t\t\t\tconst triggerElement = document.createElement( 'div' );\r\n\t\t\t\t\ttriggerElement.className = 'scrollbar-trigger';\r\n\t\t\t\t\ttriggerElement.style.top = ( trigger.range[0] - slideTrigger.range[0] ) * this.progressBarHeight + 'px';\r\n\t\t\t\t\ttriggerElement.style.height = ( trigger.range[1] - trigger.range[0] ) * this.progressBarHeight - spacing + 'px';\r\n\t\t\t\t\tpage.progressBarSlide.appendChild( triggerElement );\r\n\r\n\t\t\t\t\tif( i === 0 ) triggerElement.style.display = 'none';\r\n\r\n\t\t\t\t\treturn triggerElement;\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\t\telse {\r\n\r\n\t\t\tthis.pages.forEach( page => page.progressBarSlide = null );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Reads the current scroll position and updates our active\r\n\t * trigger states accordingly.\r\n\t */\r\n\tsyncScrollPosition() {\r\n\r\n\t\tconst viewportHeight = this.viewportElement.offsetHeight;\r\n\t\tconst viewportHeightFactor = viewportHeight / this.viewportElement.scrollHeight;\r\n\r\n\t\tconst scrollTop = this.viewportElement.scrollTop;\r\n\t\tconst scrollHeight = this.viewportElement.scrollHeight - viewportHeight\r\n\t\tconst scrollProgress = Math.max( Math.min( scrollTop / scrollHeight, 1 ), 0 );\r\n\t\tconst scrollProgressMid = Math.max( Math.min( ( scrollTop + viewportHeight / 2 ) / this.viewportElement.scrollHeight, 1 ), 0 );\r\n\r\n\t\tlet activePage;\r\n\r\n\t\tthis.slideTriggers.forEach( ( trigger ) => {\r\n\t\t\tconst { page } = trigger;\r\n\r\n\t\t\tconst shouldPreload = scrollProgress >= trigger.range[0] - viewportHeightFactor*2 &&\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tscrollProgress <= trigger.range[1] + viewportHeightFactor*2;\r\n\r\n\t\t\t// Load slides that are within the preload range\r\n\t\t\tif( shouldPreload && !page.loaded ) {\r\n\t\t\t\tpage.loaded = true;\r\n\t\t\t\tthis.Reveal.slideContent.load( page.slideElement );\r\n\t\t\t}\r\n\t\t\telse if( page.loaded ) {\r\n\t\t\t\tpage.loaded = false;\r\n\t\t\t\tthis.Reveal.slideContent.unload( page.slideElement );\r\n\t\t\t}\r\n\r\n\t\t\t// If we're within this trigger range, activate it\r\n\t\t\tif( scrollProgress >= trigger.range[0] && scrollProgress <= trigger.range[1] ) {\r\n\t\t\t\tthis.activateTrigger( trigger );\r\n\t\t\t\tactivePage = trigger.page;\r\n\t\t\t}\r\n\t\t\t// .. otherwise deactivate\r\n\t\t\telse if( trigger.active ) {\r\n\t\t\t\tthis.deactivateTrigger( trigger );\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t// Each page can have its own scroll triggers, check if any of those\r\n\t\t// need to be activated/deactivated\r\n\t\tif( activePage ) {\r\n\t\t\tactivePage.scrollTriggers.forEach( ( trigger ) => {\r\n\t\t\t\tif( scrollProgressMid >= trigger.range[0] && scrollProgressMid <= trigger.range[1] ) {\r\n\t\t\t\t\tthis.activateTrigger( trigger );\r\n\t\t\t\t}\r\n\t\t\t\telse if( trigger.active ) {\r\n\t\t\t\t\tthis.deactivateTrigger( trigger );\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\t\t// Update our visual progress indication\r\n\t\tthis.setProgressBarValue( scrollTop / ( this.viewportElement.scrollHeight - viewportHeight ) );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Moves the progress bar playhead to the specified position.\r\n\t *\r\n\t * @param {number} progress 0-1\r\n\t */\r\n\tsetProgressBarValue( progress ) {\r\n\r\n\t\tif( this.progressBar ) {\r\n\r\n\t\t\tthis.progressBarPlayhead.style.transform = `translateY(${progress * this.progressBarScrollableHeight}px)`;\r\n\r\n\t\t\tthis.getAllPages()\r\n\t\t\t\t.filter( page => page.progressBarSlide )\r\n\t\t\t\t.forEach( ( page ) => {\r\n\t\t\t\t\tpage.progressBarSlide.classList.toggle( 'active', page.active === true );\r\n\r\n\t\t\t\t\tpage.scrollTriggers.forEach( ( trigger, i ) => {\r\n\t\t\t\t\t\tpage.scrollTriggerElements[i].classList.toggle( 'active', page.active === true && trigger.active === true );\r\n\t\t\t\t\t} );\r\n\t\t\t\t} );\r\n\r\n\t\t\tthis.showProgressBar();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Show the progress bar and, if configured, automatically hide\r\n\t * it after a delay.\r\n\t */\r\n\tshowProgressBar() {\r\n\r\n\t\tthis.progressBar.classList.add( 'visible' );\r\n\r\n\t\tclearTimeout( this.hideProgressBarTimeout );\r\n\r\n\t\tif( this.Reveal.getConfig().scrollProgress === 'auto' && !this.draggingProgressBar ) {\r\n\r\n\t\t\tthis.hideProgressBarTimeout = setTimeout( () => {\r\n\t\t\t\tif( this.progressBar ) {\r\n\t\t\t\t\tthis.progressBar.classList.remove( 'visible' );\r\n\t\t\t\t}\r\n\t\t\t}, HIDE_SCROLLBAR_TIMEOUT );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Scroll to the previous page.\r\n\t */\r\n\tprev() {\r\n\r\n\t\tthis.viewportElement.scrollTop -= this.scrollTriggerHeight;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Scroll to the next page.\r\n\t */\r\n\tnext() {\r\n\r\n\t\tthis.viewportElement.scrollTop += this.scrollTriggerHeight;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Scrolls the given slide element into view.\r\n\t *\r\n\t * @param {HTMLElement} slideElement\r\n\t */\r\n\tscrollToSlide( slideElement ) {\r\n\r\n\t\t// If the scroll view isn't active yet, queue this action\r\n\t\tif( !this.active ) {\r\n\t\t\tthis.activatedCallbacks.push( () => this.scrollToSlide( slideElement ) );\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// Find the trigger for this slide\r\n\t\t\tconst trigger = this.getScrollTriggerBySlide( slideElement );\r\n\r\n\t\t\tif( trigger ) {\r\n\t\t\t\t// Use the trigger's range to calculate the scroll position\r\n\t\t\t\tthis.viewportElement.scrollTop = trigger.range[0] * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Persists the current scroll position to session storage\r\n\t * so that it can be restored.\r\n\t */\r\n\tstoreScrollPosition() {\r\n\r\n\t\tclearTimeout( this.storeScrollPositionTimeout );\r\n\r\n\t\tthis.storeScrollPositionTimeout = setTimeout( () => {\r\n\t\t\tsessionStorage.setItem( 'reveal-scroll-top', this.viewportElement.scrollTop );\r\n\t\t\tsessionStorage.setItem( 'reveal-scroll-origin', location.origin + location.pathname );\r\n\r\n\t\t\tthis.storeScrollPositionTimeout = null;\r\n\t\t}, 50 );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Restores the scroll position when a deck is reloader.\r\n\t */\r\n\trestoreScrollPosition() {\r\n\r\n\t\tconst scrollPosition = sessionStorage.getItem( 'reveal-scroll-top' );\r\n\t\tconst scrollOrigin = sessionStorage.getItem( 'reveal-scroll-origin' );\r\n\r\n\t\tif( scrollPosition && scrollOrigin === location.origin + location.pathname ) {\r\n\t\t\tthis.viewportElement.scrollTop = parseInt( scrollPosition, 10 );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Activates the given page and starts its embedded content\r\n\t * if there is any.\r\n\t *\r\n\t * @param {object} page\r\n\t */\r\n\tactivatePage( page ) {\r\n\r\n\t\tif( !page.active ) {\r\n\r\n\t\t\tpage.active = true;\r\n\r\n\t\t\tconst { slideElement, backgroundElement, contentElement, indexh, indexv } = page;\r\n\r\n\t\t\tcontentElement.style.display = 'block';\r\n\r\n\t\t\tslideElement.classList.add( 'present' );\r\n\r\n\t\t\tif( backgroundElement ) {\r\n\t\t\t\tbackgroundElement.classList.add( 'present' );\r\n\t\t\t}\r\n\r\n\t\t\tthis.Reveal.setCurrentScrollPage( slideElement, indexh, indexv );\r\n\t\t\tthis.Reveal.backgrounds.bubbleSlideContrastClassToElement( slideElement, this.viewportElement );\r\n\r\n\t\t\t// If this page is part of an auto-animation there will be one\r\n\t\t\t// content element per auto-animated page. We need to show the\r\n\t\t\t// current page and hide all others.\r\n\t\t\tArray.from( contentElement.parentNode.querySelectorAll( '.scroll-page-content' ) ).forEach( sibling => {\r\n\t\t\t\tif( sibling !== contentElement ) {\r\n\t\t\t\t\tsibling.style.display = 'none';\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Deactivates the page after it has been visible.\r\n\t *\r\n\t * @param {object} page\r\n\t */\r\n\tdeactivatePage( page ) {\r\n\r\n\t\tif( page.active ) {\r\n\r\n\t\t\tpage.active = false;\r\n\t\t\tif( page.slideElement ) page.slideElement.classList.remove( 'present' );\r\n\t\t\tif( page.backgroundElement ) page.backgroundElement.classList.remove( 'present' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tactivateTrigger( trigger ) {\r\n\r\n\t\tif( !trigger.active ) {\r\n\t\t\ttrigger.active = true;\r\n\t\t\ttrigger.activate();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tdeactivateTrigger( trigger ) {\r\n\r\n\t\tif( trigger.active ) {\r\n\t\t\ttrigger.active = false;\r\n\r\n\t\t\tif( trigger.deactivate ) {\r\n\t\t\t\ttrigger.deactivate();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Retrieve a slide by its original h/v index (i.e. the indices the\r\n\t * slide had before being linearized).\r\n\t *\r\n\t * @param {number} h\r\n\t * @param {number} v\r\n\t * @returns {HTMLElement}\r\n\t */\r\n\tgetSlideByIndices( h, v ) {\r\n\r\n\t\tconst page = this.getAllPages().find( page => {\r\n\t\t\treturn page.indexh === h && page.indexv === v;\r\n\t\t} );\r\n\r\n\t\treturn page ? page.slideElement : null;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Retrieve a list of all scroll triggers for the given slide\r\n\t * DOM element.\r\n\t *\r\n\t * @param {HTMLElement} slide\r\n\t * @returns {Array}\r\n\t */\r\n\tgetScrollTriggerBySlide( slide ) {\r\n\r\n\t\treturn this.slideTriggers.find( trigger => trigger.page.slideElement === slide );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Get a list of all pages in the scroll view. This includes\r\n\t * both top-level slides and auto-animate steps.\r\n\t *\r\n\t * @returns {Array}\r\n\t */\r\n\tgetAllPages() {\r\n\r\n\t\treturn this.pages.flatMap( page => [page, ...(page.autoAnimatePages || [])] );\r\n\r\n\t}\r\n\r\n\tonScroll() {\r\n\r\n\t\tthis.syncScrollPosition();\r\n\t\tthis.storeScrollPosition();\r\n\r\n\t}\r\n\r\n\tget viewportElement() {\r\n\r\n\t\treturn this.Reveal.getViewportElement();\r\n\r\n\t}\r\n\r\n}\r\n","import { SLIDES_SELECTOR } from '../utils/constants.js'\r\nimport { queryAll, createStyleSheet } from '../utils/util.js'\r\n\r\n/**\r\n * Setups up our presentation for printing/exporting to PDF.\r\n */\r\nexport default class PrintView {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Configures the presentation for printing to a static\r\n\t * PDF.\r\n\t */\r\n\tasync activate() {\r\n\r\n\t\tconst config = this.Reveal.getConfig();\r\n\t\tconst slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR )\r\n\r\n\t\t// Compute slide numbers now, before we start duplicating slides\r\n\t\tconst injectPageNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber );\r\n\r\n\t\tconst slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );\r\n\r\n\t\t// Dimensions of the PDF pages\r\n\t\tconst pageWidth = Math.floor( slideSize.width * ( 1 + config.margin ) ),\r\n\t\t\tpageHeight = Math.floor( slideSize.height * ( 1 + config.margin ) );\r\n\r\n\t\t// Dimensions of slides within the pages\r\n\t\tconst slideWidth = slideSize.width,\r\n\t\t\tslideHeight = slideSize.height;\r\n\r\n\t\tawait new Promise( requestAnimationFrame );\r\n\r\n\t\t// Let the browser know what page size we want to print\r\n\t\tcreateStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' );\r\n\r\n\t\t// Limit the size of certain elements to the dimensions of the slide\r\n\t\tcreateStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );\r\n\r\n\t\tdocument.documentElement.classList.add( 'reveal-print', 'print-pdf' );\r\n\t\tdocument.body.style.width = pageWidth + 'px';\r\n\t\tdocument.body.style.height = pageHeight + 'px';\r\n\r\n\t\tconst viewportElement = this.Reveal.getViewportElement();\r\n\t\tlet presentationBackground;\r\n\t\tif( viewportElement ) {\r\n\t\t\tconst viewportStyles = window.getComputedStyle( viewportElement );\r\n\t\t\tif( viewportStyles && viewportStyles.background ) {\r\n\t\t\t\tpresentationBackground = viewportStyles.background;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Make sure stretch elements fit on slide\r\n\t\tawait new Promise( requestAnimationFrame );\r\n\t\tthis.Reveal.layoutSlideContents( slideWidth, slideHeight );\r\n\r\n\t\t// Batch scrollHeight access to prevent layout thrashing\r\n\t\tawait new Promise( requestAnimationFrame );\r\n\r\n\t\tconst slideScrollHeights = slides.map( slide => slide.scrollHeight );\r\n\r\n\t\tconst pages = [];\r\n\t\tconst pageContainer = slides[0].parentNode;\r\n\t\tlet slideNumber = 1;\r\n\r\n\t\t// Slide and slide background layout\r\n\t\tslides.forEach( function( slide, index ) {\r\n\r\n\t\t\t// Vertical stacks are not centred since their section\r\n\t\t\t// children will be\r\n\t\t\tif( slide.classList.contains( 'stack' ) === false ) {\r\n\t\t\t\t// Center the slide inside of the page, giving the slide some margin\r\n\t\t\t\tlet left = ( pageWidth - slideWidth ) / 2;\r\n\t\t\t\tlet top = ( pageHeight - slideHeight ) / 2;\r\n\r\n\t\t\t\tconst contentHeight = slideScrollHeights[ index ];\r\n\t\t\t\tlet numberOfPages = Math.max( Math.ceil( contentHeight / pageHeight ), 1 );\r\n\r\n\t\t\t\t// Adhere to configured pages per slide limit\r\n\t\t\t\tnumberOfPages = Math.min( numberOfPages, config.pdfMaxPagesPerSlide );\r\n\r\n\t\t\t\t// Center slides vertically\r\n\t\t\t\tif( numberOfPages === 1 && config.center || slide.classList.contains( 'center' ) ) {\r\n\t\t\t\t\ttop = Math.max( ( pageHeight - contentHeight ) / 2, 0 );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Wrap the slide in a page element and hide its overflow\r\n\t\t\t\t// so that no page ever flows onto another\r\n\t\t\t\tconst page = document.createElement( 'div' );\r\n\t\t\t\tpages.push( page );\r\n\r\n\t\t\t\tpage.className = 'pdf-page';\r\n\t\t\t\tpage.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px';\r\n\r\n\t\t\t\t// Copy the presentation-wide background to each individual\r\n\t\t\t\t// page when printing\r\n\t\t\t\tif( presentationBackground ) {\r\n\t\t\t\t\tpage.style.background = presentationBackground;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpage.appendChild( slide );\r\n\r\n\t\t\t\t// Position the slide inside of the page\r\n\t\t\t\tslide.style.left = left + 'px';\r\n\t\t\t\tslide.style.top = top + 'px';\r\n\t\t\t\tslide.style.width = slideWidth + 'px';\r\n\r\n\t\t\t\tthis.Reveal.slideContent.layout( slide );\r\n\r\n\t\t\t\tif( slide.slideBackgroundElement ) {\r\n\t\t\t\t\tpage.insertBefore( slide.slideBackgroundElement, slide );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Inject notes if `showNotes` is enabled\r\n\t\t\t\tif( config.showNotes ) {\r\n\r\n\t\t\t\t\t// Are there notes for this slide?\r\n\t\t\t\t\tconst notes = this.Reveal.getSlideNotes( slide );\r\n\t\t\t\t\tif( notes ) {\r\n\r\n\t\t\t\t\t\tconst notesSpacing = 8;\r\n\t\t\t\t\t\tconst notesLayout = typeof config.showNotes === 'string' ? config.showNotes : 'inline';\r\n\t\t\t\t\t\tconst notesElement = document.createElement( 'div' );\r\n\t\t\t\t\t\tnotesElement.classList.add( 'speaker-notes' );\r\n\t\t\t\t\t\tnotesElement.classList.add( 'speaker-notes-pdf' );\r\n\t\t\t\t\t\tnotesElement.setAttribute( 'data-layout', notesLayout );\r\n\t\t\t\t\t\tnotesElement.innerHTML = notes;\r\n\r\n\t\t\t\t\t\tif( notesLayout === 'separate-page' ) {\r\n\t\t\t\t\t\t\tpages.push( notesElement );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\tnotesElement.style.left = notesSpacing + 'px';\r\n\t\t\t\t\t\t\tnotesElement.style.bottom = notesSpacing + 'px';\r\n\t\t\t\t\t\t\tnotesElement.style.width = ( pageWidth - notesSpacing*2 ) + 'px';\r\n\t\t\t\t\t\t\tpage.appendChild( notesElement );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Inject page numbers if `slideNumbers` are enabled\r\n\t\t\t\tif( injectPageNumbers ) {\r\n\t\t\t\t\tconst numberElement = document.createElement( 'div' );\r\n\t\t\t\t\tnumberElement.classList.add( 'slide-number' );\r\n\t\t\t\t\tnumberElement.classList.add( 'slide-number-pdf' );\r\n\t\t\t\t\tnumberElement.innerHTML = slideNumber++;\r\n\t\t\t\t\tpage.appendChild( numberElement );\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Copy page and show fragments one after another\r\n\t\t\t\tif( config.pdfSeparateFragments ) {\r\n\r\n\t\t\t\t\t// Each fragment 'group' is an array containing one or more\r\n\t\t\t\t\t// fragments. Multiple fragments that appear at the same time\r\n\t\t\t\t\t// are part of the same group.\r\n\t\t\t\t\tconst fragmentGroups = this.Reveal.fragments.sort( page.querySelectorAll( '.fragment' ), true );\r\n\r\n\t\t\t\t\tlet previousFragmentStep;\r\n\r\n\t\t\t\t\tfragmentGroups.forEach( function( fragments, index ) {\r\n\r\n\t\t\t\t\t\t// Remove 'current-fragment' from the previous group\r\n\t\t\t\t\t\tif( previousFragmentStep ) {\r\n\t\t\t\t\t\t\tpreviousFragmentStep.forEach( function( fragment ) {\r\n\t\t\t\t\t\t\t\tfragment.classList.remove( 'current-fragment' );\r\n\t\t\t\t\t\t\t} );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// Show the fragments for the current index\r\n\t\t\t\t\t\tfragments.forEach( function( fragment ) {\r\n\t\t\t\t\t\t\tfragment.classList.add( 'visible', 'current-fragment' );\r\n\t\t\t\t\t\t}, this );\r\n\r\n\t\t\t\t\t\t// Create a separate page for the current fragment state\r\n\t\t\t\t\t\tconst clonedPage = page.cloneNode( true );\r\n\r\n\t\t\t\t\t\t// Inject unique page numbers for fragments\r\n\t\t\t\t\t\tif( injectPageNumbers ) {\r\n\t\t\t\t\t\t\tconst numberElement = clonedPage.querySelector( '.slide-number-pdf' );\r\n\t\t\t\t\t\t\tconst fragmentNumber = index + 1;\r\n\t\t\t\t\t\t\tnumberElement.innerHTML += '.' + fragmentNumber;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tpages.push( clonedPage );\r\n\r\n\t\t\t\t\t\tpreviousFragmentStep = fragments;\r\n\r\n\t\t\t\t\t}, this );\r\n\r\n\t\t\t\t\t// Reset the first/original page so that all fragments are hidden\r\n\t\t\t\t\tfragmentGroups.forEach( function( fragments ) {\r\n\t\t\t\t\t\tfragments.forEach( function( fragment ) {\r\n\t\t\t\t\t\t\tfragment.classList.remove( 'visible', 'current-fragment' );\r\n\t\t\t\t\t\t} );\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t}\r\n\t\t\t\t// Show all fragments\r\n\t\t\t\telse {\r\n\t\t\t\t\tqueryAll( page, '.fragment:not(.fade-out)' ).forEach( function( fragment ) {\r\n\t\t\t\t\t\tfragment.classList.add( 'visible' );\r\n\t\t\t\t\t} );\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}, this );\r\n\r\n\t\tawait new Promise( requestAnimationFrame );\r\n\r\n\t\tpages.forEach( page => pageContainer.appendChild( page ) );\r\n\r\n\t\t// Re-run JS-based content layout after the slide is added to page DOM\r\n\t\tthis.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );\r\n\r\n\t\t// Notify subscribers that the PDF layout is good to go\r\n\t\tthis.Reveal.dispatchEvent({ type: 'pdf-ready' });\r\n\r\n\t\tviewportElement.classList.remove( 'loading-scroll-mode' );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if the print mode is/should be activated.\r\n\t */\r\n\tisActive() {\r\n\r\n\t\treturn this.Reveal.getConfig().view === 'print';\r\n\r\n\t}\r\n\r\n}","import { extend, queryAll } from '../utils/util.js'\r\n\r\n/**\r\n * Handles sorting and navigation of slide fragments.\r\n * Fragments are elements within a slide that are\r\n * revealed/animated incrementally.\r\n */\r\nexport default class Fragments {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tif( config.fragments === false ) {\r\n\t\t\tthis.disable();\r\n\t\t}\r\n\t\telse if( oldConfig.fragments === false ) {\r\n\t\t\tthis.enable();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * If fragments are disabled in the deck, they should all be\r\n\t * visible rather than stepped through.\r\n\t */\r\n\tdisable() {\r\n\r\n\t\tqueryAll( this.Reveal.getSlidesElement(), '.fragment' ).forEach( element => {\r\n\t\t\telement.classList.add( 'visible' );\r\n\t\t\telement.classList.remove( 'current-fragment' );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Reverse of #disable(). Only called if fragments have\r\n\t * previously been disabled.\r\n\t */\r\n\tenable() {\r\n\r\n\t\tqueryAll( this.Reveal.getSlidesElement(), '.fragment' ).forEach( element => {\r\n\t\t\telement.classList.remove( 'visible' );\r\n\t\t\telement.classList.remove( 'current-fragment' );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns an object describing the available fragment\r\n\t * directions.\r\n\t *\r\n\t * @return {{prev: boolean, next: boolean}}\r\n\t */\r\n\tavailableRoutes() {\r\n\r\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\r\n\t\tif( currentSlide && this.Reveal.getConfig().fragments ) {\r\n\t\t\tlet fragments = currentSlide.querySelectorAll( '.fragment:not(.disabled)' );\r\n\t\t\tlet hiddenFragments = currentSlide.querySelectorAll( '.fragment:not(.disabled):not(.visible)' );\r\n\r\n\t\t\treturn {\r\n\t\t\t\tprev: fragments.length - hiddenFragments.length > 0,\r\n\t\t\t\tnext: !!hiddenFragments.length\r\n\t\t\t};\r\n\t\t}\r\n\t\telse {\r\n\t\t\treturn { prev: false, next: false };\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Return a sorted fragments list, ordered by an increasing\r\n\t * \"data-fragment-index\" attribute.\r\n\t *\r\n\t * Fragments will be revealed in the order that they are returned by\r\n\t * this function, so you can use the index attributes to control the\r\n\t * order of fragment appearance.\r\n\t *\r\n\t * To maintain a sensible default fragment order, fragments are presumed\r\n\t * to be passed in document order. This function adds a \"fragment-index\"\r\n\t * attribute to each node if such an attribute is not already present,\r\n\t * and sets that attribute to an integer value which is the position of\r\n\t * the fragment within the fragments list.\r\n\t *\r\n\t * @param {object[]|*} fragments\r\n\t * @param {boolean} grouped If true the returned array will contain\r\n\t * nested arrays for all fragments with the same index\r\n\t * @return {object[]} sorted Sorted array of fragments\r\n\t */\r\n\tsort( fragments, grouped = false ) {\r\n\r\n\t\tfragments = Array.from( fragments );\r\n\r\n\t\tlet ordered = [],\r\n\t\t\tunordered = [],\r\n\t\t\tsorted = [];\r\n\r\n\t\t// Group ordered and unordered elements\r\n\t\tfragments.forEach( fragment => {\r\n\t\t\tif( fragment.hasAttribute( 'data-fragment-index' ) ) {\r\n\t\t\t\tlet index = parseInt( fragment.getAttribute( 'data-fragment-index' ), 10 );\r\n\r\n\t\t\t\tif( !ordered[index] ) {\r\n\t\t\t\t\tordered[index] = [];\r\n\t\t\t\t}\r\n\r\n\t\t\t\tordered[index].push( fragment );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tunordered.push( [ fragment ] );\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t// Append fragments without explicit indices in their\r\n\t\t// DOM order\r\n\t\tordered = ordered.concat( unordered );\r\n\r\n\t\t// Manually count the index up per group to ensure there\r\n\t\t// are no gaps\r\n\t\tlet index = 0;\r\n\r\n\t\t// Push all fragments in their sorted order to an array,\r\n\t\t// this flattens the groups\r\n\t\tordered.forEach( group => {\r\n\t\t\tgroup.forEach( fragment => {\r\n\t\t\t\tsorted.push( fragment );\r\n\t\t\t\tfragment.setAttribute( 'data-fragment-index', index );\r\n\t\t\t} );\r\n\r\n\t\t\tindex ++;\r\n\t\t} );\r\n\r\n\t\treturn grouped === true ? ordered : sorted;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Sorts and formats all of fragments in the\r\n\t * presentation.\r\n\t */\r\n\tsortAll() {\r\n\r\n\t\tthis.Reveal.getHorizontalSlides().forEach( horizontalSlide => {\r\n\r\n\t\t\tlet verticalSlides = queryAll( horizontalSlide, 'section' );\r\n\t\t\tverticalSlides.forEach( ( verticalSlide, y ) => {\r\n\r\n\t\t\t\tthis.sort( verticalSlide.querySelectorAll( '.fragment' ) );\r\n\r\n\t\t\t}, this );\r\n\r\n\t\t\tif( verticalSlides.length === 0 ) this.sort( horizontalSlide.querySelectorAll( '.fragment' ) );\r\n\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Refreshes the fragments on the current slide so that they\r\n\t * have the appropriate classes (.visible + .current-fragment).\r\n\t *\r\n\t * @param {number} [index] The index of the current fragment\r\n\t * @param {array} [fragments] Array containing all fragments\r\n\t * in the current slide\r\n\t *\r\n\t * @return {{shown: array, hidden: array}}\r\n\t */\r\n\tupdate( index, fragments, slide = this.Reveal.getCurrentSlide() ) {\r\n\r\n\t\tlet changedFragments = {\r\n\t\t\tshown: [],\r\n\t\t\thidden: []\r\n\t\t};\r\n\r\n\t\tif( slide && this.Reveal.getConfig().fragments ) {\r\n\r\n\t\t\tfragments = fragments || this.sort( slide.querySelectorAll( '.fragment' ) );\r\n\r\n\t\t\tif( fragments.length ) {\r\n\r\n\t\t\t\tlet maxIndex = 0;\r\n\r\n\t\t\t\tif( typeof index !== 'number' ) {\r\n\t\t\t\t\tlet currentFragment = this.sort( slide.querySelectorAll( '.fragment.visible' ) ).pop();\r\n\t\t\t\t\tif( currentFragment ) {\r\n\t\t\t\t\t\tindex = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tArray.from( fragments ).forEach( ( el, i ) => {\r\n\r\n\t\t\t\t\tif( el.hasAttribute( 'data-fragment-index' ) ) {\r\n\t\t\t\t\t\ti = parseInt( el.getAttribute( 'data-fragment-index' ), 10 );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tmaxIndex = Math.max( maxIndex, i );\r\n\r\n\t\t\t\t\t// Visible fragments\r\n\t\t\t\t\tif( i <= index ) {\r\n\t\t\t\t\t\tlet wasVisible = el.classList.contains( 'visible' )\r\n\t\t\t\t\t\tel.classList.add( 'visible' );\r\n\t\t\t\t\t\tel.classList.remove( 'current-fragment' );\r\n\r\n\t\t\t\t\t\tif( i === index ) {\r\n\t\t\t\t\t\t\t// Announce the fragments one by one to the Screen Reader\r\n\t\t\t\t\t\t\tthis.Reveal.announceStatus( this.Reveal.getStatusText( el ) );\r\n\r\n\t\t\t\t\t\t\tel.classList.add( 'current-fragment' );\r\n\t\t\t\t\t\t\tthis.Reveal.slideContent.startEmbeddedContent( el );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif( !wasVisible ) {\r\n\t\t\t\t\t\t\tchangedFragments.shown.push( el )\r\n\t\t\t\t\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\t\t\t\t\ttarget: el,\r\n\t\t\t\t\t\t\t\ttype: 'visible',\r\n\t\t\t\t\t\t\t\tbubbles: false\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Hidden fragments\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tlet wasVisible = el.classList.contains( 'visible' )\r\n\t\t\t\t\t\tel.classList.remove( 'visible' );\r\n\t\t\t\t\t\tel.classList.remove( 'current-fragment' );\r\n\r\n\t\t\t\t\t\tif( wasVisible ) {\r\n\t\t\t\t\t\t\tthis.Reveal.slideContent.stopEmbeddedContent( el );\r\n\t\t\t\t\t\t\tchangedFragments.hidden.push( el );\r\n\t\t\t\t\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\t\t\t\t\ttarget: el,\r\n\t\t\t\t\t\t\t\ttype: 'hidden',\r\n\t\t\t\t\t\t\t\tbubbles: false\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t// Write the current fragment index to the slide
.\r\n\t\t\t\t// This can be used by end users to apply styles based on\r\n\t\t\t\t// the current fragment index.\r\n\t\t\t\tindex = typeof index === 'number' ? index : -1;\r\n\t\t\t\tindex = Math.max( Math.min( index, maxIndex ), -1 );\r\n\t\t\t\tslide.setAttribute( 'data-fragment', index );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif( changedFragments.hidden.length ) {\r\n\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\ttype: 'fragmenthidden',\r\n\t\t\t\tdata: {\r\n\t\t\t\t\tfragment: changedFragments.hidden[0],\r\n\t\t\t\t\tfragments: changedFragments.hidden\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tif( changedFragments.shown.length ) {\r\n\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\ttype: 'fragmentshown',\r\n\t\t\t\tdata: {\r\n\t\t\t\t\tfragment: changedFragments.shown[0],\r\n\t\t\t\t\tfragments: changedFragments.shown\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn changedFragments;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Formats the fragments on the given slide so that they have\r\n\t * valid indices. Call this if fragments are changed in the DOM\r\n\t * after reveal.js has already initialized.\r\n\t *\r\n\t * @param {HTMLElement} slide\r\n\t * @return {Array} a list of the HTML fragments that were synced\r\n\t */\r\n\tsync( slide = this.Reveal.getCurrentSlide() ) {\r\n\r\n\t\treturn this.sort( slide.querySelectorAll( '.fragment' ) );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Navigate to the specified slide fragment.\r\n\t *\r\n\t * @param {?number} index The index of the fragment that\r\n\t * should be shown, -1 means all are invisible\r\n\t * @param {number} offset Integer offset to apply to the\r\n\t * fragment index\r\n\t *\r\n\t * @return {boolean} true if a change was made in any\r\n\t * fragments visibility as part of this call\r\n\t */\r\n\tgoto( index, offset = 0 ) {\r\n\r\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\r\n\t\tif( currentSlide && this.Reveal.getConfig().fragments ) {\r\n\r\n\t\t\tlet fragments = this.sort( currentSlide.querySelectorAll( '.fragment:not(.disabled)' ) );\r\n\t\t\tif( fragments.length ) {\r\n\r\n\t\t\t\t// If no index is specified, find the current\r\n\t\t\t\tif( typeof index !== 'number' ) {\r\n\t\t\t\t\tlet lastVisibleFragment = this.sort( currentSlide.querySelectorAll( '.fragment:not(.disabled).visible' ) ).pop();\r\n\r\n\t\t\t\t\tif( lastVisibleFragment ) {\r\n\t\t\t\t\t\tindex = parseInt( lastVisibleFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tindex = -1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Apply the offset if there is one\r\n\t\t\t\tindex += offset;\r\n\r\n\t\t\t\tlet changedFragments = this.update( index, fragments );\r\n\r\n\t\t\t\tthis.Reveal.controls.update();\r\n\t\t\t\tthis.Reveal.progress.update();\r\n\r\n\t\t\t\tif( this.Reveal.getConfig().fragmentInURL ) {\r\n\t\t\t\t\tthis.Reveal.location.writeURL();\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn !!( changedFragments.shown.length || changedFragments.hidden.length );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Navigate to the next slide fragment.\r\n\t *\r\n\t * @return {boolean} true if there was a next fragment,\r\n\t * false otherwise\r\n\t */\r\n\tnext() {\r\n\r\n\t\treturn this.goto( null, 1 );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Navigate to the previous slide fragment.\r\n\t *\r\n\t * @return {boolean} true if there was a previous fragment,\r\n\t * false otherwise\r\n\t */\r\n\tprev() {\r\n\r\n\t\treturn this.goto( null, -1 );\r\n\r\n\t}\r\n\r\n}","import { SLIDES_SELECTOR } from '../utils/constants.js'\r\nimport { extend, queryAll, transformElement } from '../utils/util.js'\r\n\r\n/**\r\n * Handles all logic related to the overview mode\r\n * (birds-eye view of all slides).\r\n */\r\nexport default class Overview {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.active = false;\r\n\r\n\t\tthis.onSlideClicked = this.onSlideClicked.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Displays the overview of slides (quick nav) by scaling\r\n\t * down and arranging all slide elements.\r\n\t */\r\n\tactivate() {\r\n\r\n\t\t// Only proceed if enabled in config\r\n\t\tif( this.Reveal.getConfig().overview && !this.Reveal.isScrollView() && !this.isActive() ) {\r\n\r\n\t\t\tthis.active = true;\r\n\r\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'overview' );\r\n\r\n\t\t\t// Don't auto-slide while in overview mode\r\n\t\t\tthis.Reveal.cancelAutoSlide();\r\n\r\n\t\t\t// Move the backgrounds element into the slide container to\r\n\t\t\t// that the same scaling is applied\r\n\t\t\tthis.Reveal.getSlidesElement().appendChild( this.Reveal.getBackgroundsElement() );\r\n\r\n\t\t\t// Clicking on an overview slide navigates to it\r\n\t\t\tqueryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( slide => {\r\n\t\t\t\tif( !slide.classList.contains( 'stack' ) ) {\r\n\t\t\t\t\tslide.addEventListener( 'click', this.onSlideClicked, true );\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\t// Calculate slide sizes\r\n\t\t\tconst margin = 70;\r\n\t\t\tconst slideSize = this.Reveal.getComputedSlideSize();\r\n\t\t\tthis.overviewSlideWidth = slideSize.width + margin;\r\n\t\t\tthis.overviewSlideHeight = slideSize.height + margin;\r\n\r\n\t\t\t// Reverse in RTL mode\r\n\t\t\tif( this.Reveal.getConfig().rtl ) {\r\n\t\t\t\tthis.overviewSlideWidth = -this.overviewSlideWidth;\r\n\t\t\t}\r\n\r\n\t\t\tthis.Reveal.updateSlidesVisibility();\r\n\r\n\t\t\tthis.layout();\r\n\t\t\tthis.update();\r\n\r\n\t\t\tthis.Reveal.layout();\r\n\r\n\t\t\tconst indices = this.Reveal.getIndices();\r\n\r\n\t\t\t// Notify observers of the overview showing\r\n\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\ttype: 'overviewshown',\r\n\t\t\t\tdata: {\r\n\t\t\t\t\t'indexh': indices.h,\r\n\t\t\t\t\t'indexv': indices.v,\r\n\t\t\t\t\t'currentSlide': this.Reveal.getCurrentSlide()\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Uses CSS transforms to position all slides in a grid for\r\n\t * display inside of the overview mode.\r\n\t */\r\n\tlayout() {\r\n\r\n\t\t// Layout slides\r\n\t\tthis.Reveal.getHorizontalSlides().forEach( ( hslide, h ) => {\r\n\t\t\thslide.setAttribute( 'data-index-h', h );\r\n\t\t\ttransformElement( hslide, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' );\r\n\r\n\t\t\tif( hslide.classList.contains( 'stack' ) ) {\r\n\r\n\t\t\t\tqueryAll( hslide, 'section' ).forEach( ( vslide, v ) => {\r\n\t\t\t\t\tvslide.setAttribute( 'data-index-h', h );\r\n\t\t\t\t\tvslide.setAttribute( 'data-index-v', v );\r\n\r\n\t\t\t\t\ttransformElement( vslide, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' );\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\t// Layout slide backgrounds\r\n\t\tArray.from( this.Reveal.getBackgroundsElement().childNodes ).forEach( ( hbackground, h ) => {\r\n\t\t\ttransformElement( hbackground, 'translate3d(' + ( h * this.overviewSlideWidth ) + 'px, 0, 0)' );\r\n\r\n\t\t\tqueryAll( hbackground, '.slide-background' ).forEach( ( vbackground, v ) => {\r\n\t\t\t\ttransformElement( vbackground, 'translate3d(0, ' + ( v * this.overviewSlideHeight ) + 'px, 0)' );\r\n\t\t\t} );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Moves the overview viewport to the current slides.\r\n\t * Called each time the current slide changes.\r\n\t */\r\n\tupdate() {\r\n\r\n\t\tconst vmin = Math.min( window.innerWidth, window.innerHeight );\r\n\t\tconst scale = Math.max( vmin / 5, 150 ) / vmin;\r\n\t\tconst indices = this.Reveal.getIndices();\r\n\r\n\t\tthis.Reveal.transformSlides( {\r\n\t\t\toverview: [\r\n\t\t\t\t'scale('+ scale +')',\r\n\t\t\t\t'translateX('+ ( -indices.h * this.overviewSlideWidth ) +'px)',\r\n\t\t\t\t'translateY('+ ( -indices.v * this.overviewSlideHeight ) +'px)'\r\n\t\t\t].join( ' ' )\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Exits the slide overview and enters the currently\r\n\t * active slide.\r\n\t */\r\n\tdeactivate() {\r\n\r\n\t\t// Only proceed if enabled in config\r\n\t\tif( this.Reveal.getConfig().overview ) {\r\n\r\n\t\t\tthis.active = false;\r\n\r\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'overview' );\r\n\r\n\t\t\t// Temporarily add a class so that transitions can do different things\r\n\t\t\t// depending on whether they are exiting/entering overview, or just\r\n\t\t\t// moving from slide to slide\r\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'overview-deactivating' );\r\n\r\n\t\t\tsetTimeout( () => {\r\n\t\t\t\tthis.Reveal.getRevealElement().classList.remove( 'overview-deactivating' );\r\n\t\t\t}, 1 );\r\n\r\n\t\t\t// Move the background element back out\r\n\t\t\tthis.Reveal.getRevealElement().appendChild( this.Reveal.getBackgroundsElement() );\r\n\r\n\t\t\t// Clean up changes made to slides\r\n\t\t\tqueryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR ).forEach( slide => {\r\n\t\t\t\ttransformElement( slide, '' );\r\n\r\n\t\t\t\tslide.removeEventListener( 'click', this.onSlideClicked, true );\r\n\t\t\t} );\r\n\r\n\t\t\t// Clean up changes made to backgrounds\r\n\t\t\tqueryAll( this.Reveal.getBackgroundsElement(), '.slide-background' ).forEach( background => {\r\n\t\t\t\ttransformElement( background, '' );\r\n\t\t\t} );\r\n\r\n\t\t\tthis.Reveal.transformSlides( { overview: '' } );\r\n\r\n\t\t\tconst indices = this.Reveal.getIndices();\r\n\r\n\t\t\tthis.Reveal.slide( indices.h, indices.v );\r\n\t\t\tthis.Reveal.layout();\r\n\t\t\tthis.Reveal.cueAutoSlide();\r\n\r\n\t\t\t// Notify observers of the overview hiding\r\n\t\t\tthis.Reveal.dispatchEvent({\r\n\t\t\t\ttype: 'overviewhidden',\r\n\t\t\t\tdata: {\r\n\t\t\t\t\t'indexh': indices.h,\r\n\t\t\t\t\t'indexv': indices.v,\r\n\t\t\t\t\t'currentSlide': this.Reveal.getCurrentSlide()\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Toggles the slide overview mode on and off.\r\n\t *\r\n\t * @param {Boolean} [override] Flag which overrides the\r\n\t * toggle logic and forcibly sets the desired state. True means\r\n\t * overview is open, false means it's closed.\r\n\t */\r\n\ttoggle( override ) {\r\n\r\n\t\tif( typeof override === 'boolean' ) {\r\n\t\t\toverride ? this.activate() : this.deactivate();\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.isActive() ? this.deactivate() : this.activate();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if the overview is currently active.\r\n\t *\r\n\t * @return {Boolean} true if the overview is active,\r\n\t * false otherwise\r\n\t */\r\n\tisActive() {\r\n\r\n\t\treturn this.active;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Invoked when a slide is and we're in the overview.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonSlideClicked( event ) {\r\n\r\n\t\tif( this.isActive() ) {\r\n\t\t\tevent.preventDefault();\r\n\r\n\t\t\tlet element = event.target;\r\n\r\n\t\t\twhile( element && !element.nodeName.match( /section/gi ) ) {\r\n\t\t\t\telement = element.parentNode;\r\n\t\t\t}\r\n\r\n\t\t\tif( element && !element.classList.contains( 'disabled' ) ) {\r\n\r\n\t\t\t\tthis.deactivate();\r\n\r\n\t\t\t\tif( element.nodeName.match( /section/gi ) ) {\r\n\t\t\t\t\tlet h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),\r\n\t\t\t\t\t\tv = parseInt( element.getAttribute( 'data-index-v' ), 10 );\r\n\r\n\t\t\t\t\tthis.Reveal.slide( h, v );\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n}","import { enterFullscreen } from '../utils/util.js'\r\n\r\n/**\r\n * Handles all reveal.js keyboard interactions.\r\n */\r\nexport default class Keyboard {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\t// A key:value map of keyboard keys and descriptions of\r\n\t\t// the actions they trigger\r\n\t\tthis.shortcuts = {};\r\n\r\n\t\t// Holds custom key code mappings\r\n\t\tthis.bindings = {};\r\n\r\n\t\tthis.onDocumentKeyDown = this.onDocumentKeyDown.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tif( config.navigationMode === 'linear' ) {\r\n\t\t\tthis.shortcuts['→ , ↓ , SPACE , N , L , J'] = 'Next slide';\r\n\t\t\tthis.shortcuts['← , ↑ , P , H , K'] = 'Previous slide';\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.shortcuts['N , SPACE'] = 'Next slide';\r\n\t\t\tthis.shortcuts['P , Shift SPACE'] = 'Previous slide';\r\n\t\t\tthis.shortcuts['← , H'] = 'Navigate left';\r\n\t\t\tthis.shortcuts['→ , L'] = 'Navigate right';\r\n\t\t\tthis.shortcuts['↑ , K'] = 'Navigate up';\r\n\t\t\tthis.shortcuts['↓ , J'] = 'Navigate down';\r\n\t\t}\r\n\r\n\t\tthis.shortcuts['Alt + ←/↑/→/↓'] = 'Navigate without fragments';\r\n\t\tthis.shortcuts['Shift + ←/↑/→/↓'] = 'Jump to first/last slide';\r\n\t\tthis.shortcuts['B , .'] = 'Pause';\r\n\t\tthis.shortcuts['F'] = 'Fullscreen';\r\n\t\tthis.shortcuts['G'] = 'Jump to slide';\r\n\t\tthis.shortcuts['ESC, O'] = 'Slide overview';\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Starts listening for keyboard events.\r\n\t */\r\n\tbind() {\r\n\r\n\t\tdocument.addEventListener( 'keydown', this.onDocumentKeyDown, false );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Stops listening for keyboard events.\r\n\t */\r\n\tunbind() {\r\n\r\n\t\tdocument.removeEventListener( 'keydown', this.onDocumentKeyDown, false );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Add a custom key binding with optional description to\r\n\t * be added to the help screen.\r\n\t */\r\n\taddKeyBinding( binding, callback ) {\r\n\r\n\t\tif( typeof binding === 'object' && binding.keyCode ) {\r\n\t\t\tthis.bindings[binding.keyCode] = {\r\n\t\t\t\tcallback: callback,\r\n\t\t\t\tkey: binding.key,\r\n\t\t\t\tdescription: binding.description\r\n\t\t\t};\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.bindings[binding] = {\r\n\t\t\t\tcallback: callback,\r\n\t\t\t\tkey: null,\r\n\t\t\t\tdescription: null\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Removes the specified custom key binding.\r\n\t */\r\n\tremoveKeyBinding( keyCode ) {\r\n\r\n\t\tdelete this.bindings[keyCode];\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Programmatically triggers a keyboard event\r\n\t *\r\n\t * @param {int} keyCode\r\n\t */\r\n\ttriggerKey( keyCode ) {\r\n\r\n\t\tthis.onDocumentKeyDown( { keyCode } );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Registers a new shortcut to include in the help overlay\r\n\t *\r\n\t * @param {String} key\r\n\t * @param {String} value\r\n\t */\r\n\tregisterKeyboardShortcut( key, value ) {\r\n\r\n\t\tthis.shortcuts[key] = value;\r\n\r\n\t}\r\n\r\n\tgetShortcuts() {\r\n\r\n\t\treturn this.shortcuts;\r\n\r\n\t}\r\n\r\n\tgetBindings() {\r\n\r\n\t\treturn this.bindings;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Handler for the document level 'keydown' event.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonDocumentKeyDown( event ) {\r\n\r\n\t\tlet config = this.Reveal.getConfig();\r\n\r\n\t\t// If there's a condition specified and it returns false,\r\n\t\t// ignore this event\r\n\t\tif( typeof config.keyboardCondition === 'function' && config.keyboardCondition(event) === false ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// If keyboardCondition is set, only capture keyboard events\r\n\t\t// for embedded decks when they are focused\r\n\t\tif( config.keyboardCondition === 'focused' && !this.Reveal.isFocused() ) {\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\t// Shorthand\r\n\t\tlet keyCode = event.keyCode;\r\n\r\n\t\t// Remember if auto-sliding was paused so we can toggle it\r\n\t\tlet autoSlideWasPaused = !this.Reveal.isAutoSliding();\r\n\r\n\t\tthis.Reveal.onUserInput( event );\r\n\r\n\t\t// Is there a focused element that could be using the keyboard?\r\n\t\tlet activeElementIsCE = document.activeElement && document.activeElement.isContentEditable === true;\r\n\t\tlet activeElementIsInput = document.activeElement && document.activeElement.tagName && /input|textarea/i.test( document.activeElement.tagName );\r\n\t\tlet activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);\r\n\r\n\t\t// Whitelist certain modifiers for slide navigation shortcuts\r\n\t\tlet keyCodeUsesModifier = [32, 37, 38, 39, 40, 78, 80, 191].indexOf( event.keyCode ) !== -1;\r\n\r\n\t\t// Prevent all other events when a modifier is pressed\r\n\t\tlet unusedModifier = \t!( keyCodeUsesModifier && event.shiftKey || event.altKey ) &&\r\n\t\t\t\t\t\t\t\t( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey );\r\n\r\n\t\t// Disregard the event if there's a focused element or a\r\n\t\t// keyboard modifier key is present\r\n\t\tif( activeElementIsCE || activeElementIsInput || activeElementIsNotes || unusedModifier ) return;\r\n\r\n\t\t// While paused only allow resume keyboard events; 'b', 'v', '.'\r\n\t\tlet resumeKeyCodes = [66,86,190,191,112];\r\n\t\tlet key;\r\n\r\n\t\t// Custom key bindings for togglePause should be able to resume\r\n\t\tif( typeof config.keyboard === 'object' ) {\r\n\t\t\tfor( key in config.keyboard ) {\r\n\t\t\t\tif( config.keyboard[key] === 'togglePause' ) {\r\n\t\t\t\t\tresumeKeyCodes.push( parseInt( key, 10 ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( this.Reveal.isPaused() && resumeKeyCodes.indexOf( keyCode ) === -1 ) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// Use linear navigation if we're configured to OR if\r\n\t\t// the presentation is one-dimensional\r\n\t\tlet useLinearMode = config.navigationMode === 'linear' || !this.Reveal.hasHorizontalSlides() || !this.Reveal.hasVerticalSlides();\r\n\r\n\t\tlet triggered = false;\r\n\r\n\t\t// 1. User defined key bindings\r\n\t\tif( typeof config.keyboard === 'object' ) {\r\n\r\n\t\t\tfor( key in config.keyboard ) {\r\n\r\n\t\t\t\t// Check if this binding matches the pressed key\r\n\t\t\t\tif( parseInt( key, 10 ) === keyCode ) {\r\n\r\n\t\t\t\t\tlet value = config.keyboard[ key ];\r\n\r\n\t\t\t\t\t// Callback function\r\n\t\t\t\t\tif( typeof value === 'function' ) {\r\n\t\t\t\t\t\tvalue.apply( null, [ event ] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// String shortcuts to reveal.js API\r\n\t\t\t\t\telse if( typeof value === 'string' && typeof this.Reveal[ value ] === 'function' ) {\r\n\t\t\t\t\t\tthis.Reveal[ value ].call();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttriggered = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// 2. Registered custom key bindings\r\n\t\tif( triggered === false ) {\r\n\r\n\t\t\tfor( key in this.bindings ) {\r\n\r\n\t\t\t\t// Check if this binding matches the pressed key\r\n\t\t\t\tif( parseInt( key, 10 ) === keyCode ) {\r\n\r\n\t\t\t\t\tlet action = this.bindings[ key ].callback;\r\n\r\n\t\t\t\t\t// Callback function\r\n\t\t\t\t\tif( typeof action === 'function' ) {\r\n\t\t\t\t\t\taction.apply( null, [ event ] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// String shortcuts to reveal.js API\r\n\t\t\t\t\telse if( typeof action === 'string' && typeof this.Reveal[ action ] === 'function' ) {\r\n\t\t\t\t\t\tthis.Reveal[ action ].call();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttriggered = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// 3. System defined key bindings\r\n\t\tif( triggered === false ) {\r\n\r\n\t\t\t// Assume true and try to prove false\r\n\t\t\ttriggered = true;\r\n\r\n\t\t\t// P, PAGE UP\r\n\t\t\tif( keyCode === 80 || keyCode === 33 ) {\r\n\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\r\n\t\t\t}\r\n\t\t\t// N, PAGE DOWN\r\n\t\t\telse if( keyCode === 78 || keyCode === 34 ) {\r\n\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\r\n\t\t\t}\r\n\t\t\t// H, LEFT\r\n\t\t\telse if( keyCode === 72 || keyCode === 37 ) {\r\n\t\t\t\tif( event.shiftKey ) {\r\n\t\t\t\t\tthis.Reveal.slide( 0 );\r\n\t\t\t\t}\r\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\r\n\t\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tthis.Reveal.left({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// L, RIGHT\r\n\t\t\telse if( keyCode === 76 || keyCode === 39 ) {\r\n\t\t\t\tif( event.shiftKey ) {\r\n\t\t\t\t\tthis.Reveal.slide( this.Reveal.getHorizontalSlides().length - 1 );\r\n\t\t\t\t}\r\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\r\n\t\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tthis.Reveal.right({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// K, UP\r\n\t\t\telse if( keyCode === 75 || keyCode === 38 ) {\r\n\t\t\t\tif( event.shiftKey ) {\r\n\t\t\t\t\tthis.Reveal.slide( undefined, 0 );\r\n\t\t\t\t}\r\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\r\n\t\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tthis.Reveal.up({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// J, DOWN\r\n\t\t\telse if( keyCode === 74 || keyCode === 40 ) {\r\n\t\t\t\tif( event.shiftKey ) {\r\n\t\t\t\t\tthis.Reveal.slide( undefined, Number.MAX_VALUE );\r\n\t\t\t\t}\r\n\t\t\t\telse if( !this.Reveal.overview.isActive() && useLinearMode ) {\r\n\t\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tthis.Reveal.down({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// HOME\r\n\t\t\telse if( keyCode === 36 ) {\r\n\t\t\t\tthis.Reveal.slide( 0 );\r\n\t\t\t}\r\n\t\t\t// END\r\n\t\t\telse if( keyCode === 35 ) {\r\n\t\t\t\tthis.Reveal.slide( this.Reveal.getHorizontalSlides().length - 1 );\r\n\t\t\t}\r\n\t\t\t// SPACE\r\n\t\t\telse if( keyCode === 32 ) {\r\n\t\t\t\tif( this.Reveal.overview.isActive() ) {\r\n\t\t\t\t\tthis.Reveal.overview.deactivate();\r\n\t\t\t\t}\r\n\t\t\t\tif( event.shiftKey ) {\r\n\t\t\t\t\tthis.Reveal.prev({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tthis.Reveal.next({skipFragments: event.altKey});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS \"BLACK SCREEN\" BUTTON\r\n\t\t\telse if( [58, 59, 66, 86, 190].includes( keyCode ) || ( keyCode === 191 && !event.shiftKey ) ) {\r\n\t\t\t\tthis.Reveal.togglePause();\r\n\t\t\t}\r\n\t\t\t// F\r\n\t\t\telse if( keyCode === 70 ) {\r\n\t\t\t\tenterFullscreen( config.embedded ? this.Reveal.getViewportElement() : document.documentElement );\r\n\t\t\t}\r\n\t\t\t// A\r\n\t\t\telse if( keyCode === 65 ) {\r\n\t\t\t\tif( config.autoSlideStoppable ) {\r\n\t\t\t\t\tthis.Reveal.toggleAutoSlide( autoSlideWasPaused );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// G\r\n\t\t\telse if( keyCode === 71 ) {\r\n\t\t\t\tif( config.jumpToSlide ) {\r\n\t\t\t\t\tthis.Reveal.toggleJumpToSlide();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// ?\r\n\t\t\telse if( keyCode === 191 && event.shiftKey ) {\r\n\t\t\t\tthis.Reveal.toggleHelp();\r\n\t\t\t}\r\n\t\t\t// F1\r\n\t\t\telse if( keyCode === 112 ) {\r\n\t\t\t\tthis.Reveal.toggleHelp();\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\ttriggered = false;\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// If the input resulted in a triggered action we should prevent\r\n\t\t// the browsers default behavior\r\n\t\tif( triggered ) {\r\n\t\t\tevent.preventDefault && event.preventDefault();\r\n\t\t}\r\n\t\t// ESC or O key\r\n\t\telse if( keyCode === 27 || keyCode === 79 ) {\r\n\t\t\tif( this.Reveal.closeOverlay() === false ) {\r\n\t\t\t\tthis.Reveal.overview.toggle();\r\n\t\t\t}\r\n\r\n\t\t\tevent.preventDefault && event.preventDefault();\r\n\t\t}\r\n\r\n\t\t// If auto-sliding is enabled we need to cue up\r\n\t\t// another timeout\r\n\t\tthis.Reveal.cueAutoSlide();\r\n\r\n\t}\r\n\r\n}\r\n","/**\r\n * Reads and writes the URL based on reveal.js' current state.\r\n */\r\nexport default class Location {\r\n\r\n\t// The minimum number of milliseconds that must pass between\r\n\t// calls to history.replaceState\r\n\tMAX_REPLACE_STATE_FREQUENCY = 1000\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\t// Delays updates to the URL due to a Chrome thumbnailer bug\r\n\t\tthis.writeURLTimeout = 0;\r\n\r\n\t\tthis.replaceStateTimestamp = 0;\r\n\r\n\t\tthis.onWindowHashChange = this.onWindowHashChange.bind( this );\r\n\r\n\t}\r\n\r\n\tbind() {\r\n\r\n\t\twindow.addEventListener( 'hashchange', this.onWindowHashChange, false );\r\n\r\n\t}\r\n\r\n\tunbind() {\r\n\r\n\t\twindow.removeEventListener( 'hashchange', this.onWindowHashChange, false );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the slide indices for the given hash link.\r\n\t *\r\n\t * @param {string} [hash] the hash string that we want to\r\n\t * find the indices for\r\n\t *\r\n\t * @returns slide indices or null\r\n\t */\r\n\tgetIndicesFromHash( hash=window.location.hash, options={} ) {\r\n\r\n\t\t// Attempt to parse the hash as either an index or name\r\n\t\tlet name = hash.replace( /^#\\/?/, '' );\r\n\t\tlet bits = name.split( '/' );\r\n\r\n\t\t// If the first bit is not fully numeric and there is a name we\r\n\t\t// can assume that this is a named link\r\n\t\tif( !/^[0-9]*$/.test( bits[0] ) && name.length ) {\r\n\t\t\tlet slide;\r\n\r\n\t\t\tlet f;\r\n\r\n\t\t\t// Parse named links with fragments (#/named-link/2)\r\n\t\t\tif( /\\/[-\\d]+$/g.test( name ) ) {\r\n\t\t\t\tf = parseInt( name.split( '/' ).pop(), 10 );\r\n\t\t\t\tf = isNaN(f) ? undefined : f;\r\n\t\t\t\tname = name.split( '/' ).shift();\r\n\t\t\t}\r\n\r\n\t\t\t// Ensure the named link is a valid HTML ID attribute\r\n\t\t\ttry {\r\n\t\t\t\tslide = document\r\n\t\t\t\t\t.getElementById( decodeURIComponent( name ) )\r\n\t\t\t\t\t.closest('.slides section');\r\n\t\t\t}\r\n\t\t\tcatch ( error ) { }\r\n\r\n\t\t\tif( slide ) {\r\n\t\t\t\treturn { ...this.Reveal.getIndices( slide ), f };\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\tconst config = this.Reveal.getConfig();\r\n\t\t\tlet hashIndexBase = config.hashOneBasedIndex || options.oneBasedIndex ? 1 : 0;\r\n\r\n\t\t\t// Read the index components of the hash\r\n\t\t\tlet h = ( parseInt( bits[0], 10 ) - hashIndexBase ) || 0,\r\n\t\t\t\tv = ( parseInt( bits[1], 10 ) - hashIndexBase ) || 0,\r\n\t\t\t\tf;\r\n\r\n\t\t\tif( config.fragmentInURL ) {\r\n\t\t\t\tf = parseInt( bits[2], 10 );\r\n\t\t\t\tif( isNaN( f ) ) {\r\n\t\t\t\t\tf = undefined;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn { h, v, f };\r\n\t\t}\r\n\r\n\t\t// The hash couldn't be parsed or no matching named link was found\r\n\t\treturn null\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Reads the current URL (hash) and navigates accordingly.\r\n\t */\r\n\treadURL() {\r\n\r\n\t\tconst currentIndices = this.Reveal.getIndices();\r\n\t\tconst newIndices = this.getIndicesFromHash();\r\n\r\n\t\tif( newIndices ) {\r\n\t\t\tif( ( newIndices.h !== currentIndices.h || newIndices.v !== currentIndices.v || newIndices.f !== undefined ) ) {\r\n\t\t\t\t\tthis.Reveal.slide( newIndices.h, newIndices.v, newIndices.f );\r\n\t\t\t}\r\n\t\t}\r\n\t\t// If no new indices are available, we're trying to navigate to\r\n\t\t// a slide hash that does not exist\r\n\t\telse {\r\n\t\t\tthis.Reveal.slide( currentIndices.h || 0, currentIndices.v || 0 );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the page URL (hash) to reflect the current\r\n\t * state.\r\n\t *\r\n\t * @param {number} delay The time in ms to wait before\r\n\t * writing the hash\r\n\t */\r\n\twriteURL( delay ) {\r\n\r\n\t\tlet config = this.Reveal.getConfig();\r\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\r\n\r\n\t\t// Make sure there's never more than one timeout running\r\n\t\tclearTimeout( this.writeURLTimeout );\r\n\r\n\t\t// If a delay is specified, timeout this call\r\n\t\tif( typeof delay === 'number' ) {\r\n\t\t\tthis.writeURLTimeout = setTimeout( this.writeURL, delay );\r\n\t\t}\r\n\t\telse if( currentSlide ) {\r\n\r\n\t\t\tlet hash = this.getHash();\r\n\r\n\t\t\t// If we're configured to push to history OR the history\r\n\t\t\t// API is not available.\r\n\t\t\tif( config.history ) {\r\n\t\t\t\twindow.location.hash = hash;\r\n\t\t\t}\r\n\t\t\t// If we're configured to reflect the current slide in the\r\n\t\t\t// URL without pushing to history.\r\n\t\t\telse if( config.hash ) {\r\n\t\t\t\t// If the hash is empty, don't add it to the URL\r\n\t\t\t\tif( hash === '/' ) {\r\n\t\t\t\t\tthis.debouncedReplaceState( window.location.pathname + window.location.search );\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tthis.debouncedReplaceState( '#' + hash );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// UPDATE: The below nuking of all hash changes breaks\r\n\t\t\t// anchors on pages where reveal.js is running. Removed\r\n\t\t\t// in 4.0. Why was it here in the first place? ¯\\_(ツ)_/¯\r\n\t\t\t//\r\n\t\t\t// If history and hash are both disabled, a hash may still\r\n\t\t\t// be added to the URL by clicking on a href with a hash\r\n\t\t\t// target. Counter this by always removing the hash.\r\n\t\t\t// else {\r\n\t\t\t// \twindow.history.replaceState( null, null, window.location.pathname + window.location.search );\r\n\t\t\t// }\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\treplaceState( url ) {\r\n\r\n\t\twindow.history.replaceState( null, null, url );\r\n\t\tthis.replaceStateTimestamp = Date.now();\r\n\r\n\t}\r\n\r\n\tdebouncedReplaceState( url ) {\r\n\r\n\t\tclearTimeout( this.replaceStateTimeout );\r\n\r\n\t\tif( Date.now() - this.replaceStateTimestamp > this.MAX_REPLACE_STATE_FREQUENCY ) {\r\n\t\t\tthis.replaceState( url );\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.replaceStateTimeout = setTimeout( () => this.replaceState( url ), this.MAX_REPLACE_STATE_FREQUENCY );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Return a hash URL that will resolve to the given slide location.\r\n\t *\r\n\t * @param {HTMLElement} [slide=currentSlide] The slide to link to\r\n\t */\r\n\tgetHash( slide ) {\r\n\r\n\t\tlet url = '/';\r\n\r\n\t\t// Attempt to create a named link based on the slide's ID\r\n\t\tlet s = slide || this.Reveal.getCurrentSlide();\r\n\t\tlet id = s ? s.getAttribute( 'id' ) : null;\r\n\t\tif( id ) {\r\n\t\t\tid = encodeURIComponent( id );\r\n\t\t}\r\n\r\n\t\tlet index = this.Reveal.getIndices( slide );\r\n\t\tif( !this.Reveal.getConfig().fragmentInURL ) {\r\n\t\t\tindex.f = undefined;\r\n\t\t}\r\n\r\n\t\t// If the current slide has an ID, use that as a named link,\r\n\t\t// but we don't support named links with a fragment index\r\n\t\tif( typeof id === 'string' && id.length ) {\r\n\t\t\turl = '/' + id;\r\n\r\n\t\t\t// If there is also a fragment, append that at the end\r\n\t\t\t// of the named link, like: #/named-link/2\r\n\t\t\tif( index.f >= 0 ) url += '/' + index.f;\r\n\t\t}\r\n\t\t// Otherwise use the /h/v index\r\n\t\telse {\r\n\t\t\tlet hashIndexBase = this.Reveal.getConfig().hashOneBasedIndex ? 1 : 0;\r\n\t\t\tif( index.h > 0 || index.v > 0 || index.f >= 0 ) url += index.h + hashIndexBase;\r\n\t\t\tif( index.v > 0 || index.f >= 0 ) url += '/' + (index.v + hashIndexBase );\r\n\t\t\tif( index.f >= 0 ) url += '/' + index.f;\r\n\t\t}\r\n\r\n\t\treturn url;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Handler for the window level 'hashchange' event.\r\n\t *\r\n\t * @param {object} [event]\r\n\t */\r\n\tonWindowHashChange( event ) {\r\n\r\n\t\tthis.readURL();\r\n\r\n\t}\r\n\r\n}","import { queryAll, enterFullscreen } from '../utils/util.js'\r\nimport { isAndroid } from '../utils/device.js'\r\n\r\n/**\r\n * Manages our presentation controls. This includes both\r\n * the built-in control arrows as well as event monitoring\r\n * of any elements within the presentation with either of the\r\n * following helper classes:\r\n * - .navigate-up\r\n * - .navigate-right\r\n * - .navigate-down\r\n * - .navigate-left\r\n * - .navigate-next\r\n * - .navigate-prev\r\n * - .enter-fullscreen\r\n */\r\nexport default class Controls {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.onNavigateLeftClicked = this.onNavigateLeftClicked.bind( this );\r\n\t\tthis.onNavigateRightClicked = this.onNavigateRightClicked.bind( this );\r\n\t\tthis.onNavigateUpClicked = this.onNavigateUpClicked.bind( this );\r\n\t\tthis.onNavigateDownClicked = this.onNavigateDownClicked.bind( this );\r\n\t\tthis.onNavigatePrevClicked = this.onNavigatePrevClicked.bind( this );\r\n\t\tthis.onNavigateNextClicked = this.onNavigateNextClicked.bind( this );\r\n\t\tthis.onEnterFullscreen = this.onEnterFullscreen.bind( this );\r\n\r\n\t}\r\n\r\n\trender() {\r\n\r\n\t\tconst rtl = this.Reveal.getConfig().rtl;\r\n\t\tconst revealElement = this.Reveal.getRevealElement();\r\n\r\n\t\tthis.element = document.createElement( 'aside' );\r\n\t\tthis.element.className = 'controls';\r\n\t\tthis.element.innerHTML =\r\n\t\t\t`\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t`;\r\n\r\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\r\n\r\n\t\t// There can be multiple instances of controls throughout the page\r\n\t\tthis.controlsLeft = queryAll( revealElement, '.navigate-left' );\r\n\t\tthis.controlsRight = queryAll( revealElement, '.navigate-right' );\r\n\t\tthis.controlsUp = queryAll( revealElement, '.navigate-up' );\r\n\t\tthis.controlsDown = queryAll( revealElement, '.navigate-down' );\r\n\t\tthis.controlsPrev = queryAll( revealElement, '.navigate-prev' );\r\n\t\tthis.controlsNext = queryAll( revealElement, '.navigate-next' );\r\n\t\tthis.controlsFullscreen = queryAll( revealElement, '.enter-fullscreen' );\r\n\r\n\t\t// The left, right and down arrows in the standard reveal.js controls\r\n\t\tthis.controlsRightArrow = this.element.querySelector( '.navigate-right' );\r\n\t\tthis.controlsLeftArrow = this.element.querySelector( '.navigate-left' );\r\n\t\tthis.controlsDownArrow = this.element.querySelector( '.navigate-down' );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tthis.element.style.display = config.controls ? 'block' : 'none';\r\n\r\n\t\tthis.element.setAttribute( 'data-controls-layout', config.controlsLayout );\r\n\t\tthis.element.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows );\r\n\r\n\t}\r\n\r\n\tbind() {\r\n\r\n\t\t// Listen to both touch and click events, in case the device\r\n\t\t// supports both\r\n\t\tlet pointerEvents = [ 'touchstart', 'click' ];\r\n\r\n\t\t// Only support touch for Android, fixes double navigations in\r\n\t\t// stock browser\r\n\t\tif( isAndroid ) {\r\n\t\t\tpointerEvents = [ 'touchstart' ];\r\n\t\t}\r\n\r\n\t\tpointerEvents.forEach( eventName => {\r\n\t\t\tthis.controlsLeft.forEach( el => el.addEventListener( eventName, this.onNavigateLeftClicked, false ) );\r\n\t\t\tthis.controlsRight.forEach( el => el.addEventListener( eventName, this.onNavigateRightClicked, false ) );\r\n\t\t\tthis.controlsUp.forEach( el => el.addEventListener( eventName, this.onNavigateUpClicked, false ) );\r\n\t\t\tthis.controlsDown.forEach( el => el.addEventListener( eventName, this.onNavigateDownClicked, false ) );\r\n\t\t\tthis.controlsPrev.forEach( el => el.addEventListener( eventName, this.onNavigatePrevClicked, false ) );\r\n\t\t\tthis.controlsNext.forEach( el => el.addEventListener( eventName, this.onNavigateNextClicked, false ) );\r\n\t\t\tthis.controlsFullscreen.forEach( el => el.addEventListener( eventName, this.onEnterFullscreen, false ) );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\tunbind() {\r\n\r\n\t\t[ 'touchstart', 'click' ].forEach( eventName => {\r\n\t\t\tthis.controlsLeft.forEach( el => el.removeEventListener( eventName, this.onNavigateLeftClicked, false ) );\r\n\t\t\tthis.controlsRight.forEach( el => el.removeEventListener( eventName, this.onNavigateRightClicked, false ) );\r\n\t\t\tthis.controlsUp.forEach( el => el.removeEventListener( eventName, this.onNavigateUpClicked, false ) );\r\n\t\t\tthis.controlsDown.forEach( el => el.removeEventListener( eventName, this.onNavigateDownClicked, false ) );\r\n\t\t\tthis.controlsPrev.forEach( el => el.removeEventListener( eventName, this.onNavigatePrevClicked, false ) );\r\n\t\t\tthis.controlsNext.forEach( el => el.removeEventListener( eventName, this.onNavigateNextClicked, false ) );\r\n\t\t\tthis.controlsFullscreen.forEach( el => el.removeEventListener( eventName, this.onEnterFullscreen, false ) );\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the state of all control/navigation arrows.\r\n\t */\r\n\tupdate() {\r\n\r\n\t\tlet routes = this.Reveal.availableRoutes();\r\n\r\n\t\t// Remove the 'enabled' class from all directions\r\n\t\t[...this.controlsLeft, ...this.controlsRight, ...this.controlsUp, ...this.controlsDown, ...this.controlsPrev, ...this.controlsNext].forEach( node => {\r\n\t\t\tnode.classList.remove( 'enabled', 'fragmented' );\r\n\r\n\t\t\t// Set 'disabled' attribute on all directions\r\n\t\t\tnode.setAttribute( 'disabled', 'disabled' );\r\n\t\t} );\r\n\r\n\t\t// Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons\r\n\t\tif( routes.left ) this.controlsLeft.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\tif( routes.right ) this.controlsRight.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\tif( routes.up ) this.controlsUp.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\tif( routes.down ) this.controlsDown.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\r\n\t\t// Prev/next buttons\r\n\t\tif( routes.left || routes.up ) this.controlsPrev.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\tif( routes.right || routes.down ) this.controlsNext.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\r\n\t\t// Highlight fragment directions\r\n\t\tlet currentSlide = this.Reveal.getCurrentSlide();\r\n\t\tif( currentSlide ) {\r\n\r\n\t\t\tlet fragmentsRoutes = this.Reveal.fragments.availableRoutes();\r\n\r\n\t\t\t// Always apply fragment decorator to prev/next buttons\r\n\t\t\tif( fragmentsRoutes.prev ) this.controlsPrev.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\t\tif( fragmentsRoutes.next ) this.controlsNext.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\r\n\t\t\t// Apply fragment decorators to directional buttons based on\r\n\t\t\t// what slide axis they are in\r\n\t\t\tif( this.Reveal.isVerticalSlide( currentSlide ) ) {\r\n\t\t\t\tif( fragmentsRoutes.prev ) this.controlsUp.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\t\t\tif( fragmentsRoutes.next ) this.controlsDown.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tif( fragmentsRoutes.prev ) this.controlsLeft.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\t\t\tif( fragmentsRoutes.next ) this.controlsRight.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif( this.Reveal.getConfig().controlsTutorial ) {\r\n\r\n\t\t\tlet indices = this.Reveal.getIndices();\r\n\r\n\t\t\t// Highlight control arrows with an animation to ensure\r\n\t\t\t// that the viewer knows how to navigate\r\n\t\t\tif( !this.Reveal.hasNavigatedVertically() && routes.down ) {\r\n\t\t\t\tthis.controlsDownArrow.classList.add( 'highlight' );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tthis.controlsDownArrow.classList.remove( 'highlight' );\r\n\r\n\t\t\t\tif( this.Reveal.getConfig().rtl ) {\r\n\r\n\t\t\t\t\tif( !this.Reveal.hasNavigatedHorizontally() && routes.left && indices.v === 0 ) {\r\n\t\t\t\t\t\tthis.controlsLeftArrow.classList.add( 'highlight' );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tthis.controlsLeftArrow.classList.remove( 'highlight' );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tif( !this.Reveal.hasNavigatedHorizontally() && routes.right && indices.v === 0 ) {\r\n\t\t\t\t\t\tthis.controlsRightArrow.classList.add( 'highlight' );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tthis.controlsRightArrow.classList.remove( 'highlight' );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.unbind();\r\n\t\tthis.element.remove();\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Event handlers for navigation control buttons.\r\n\t */\r\n\tonNavigateLeftClicked( event ) {\r\n\r\n\t\tevent.preventDefault();\r\n\t\tthis.Reveal.onUserInput();\r\n\r\n\t\tif( this.Reveal.getConfig().navigationMode === 'linear' ) {\r\n\t\t\tthis.Reveal.prev();\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.Reveal.left();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tonNavigateRightClicked( event ) {\r\n\r\n\t\tevent.preventDefault();\r\n\t\tthis.Reveal.onUserInput();\r\n\r\n\t\tif( this.Reveal.getConfig().navigationMode === 'linear' ) {\r\n\t\t\tthis.Reveal.next();\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.Reveal.right();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tonNavigateUpClicked( event ) {\r\n\r\n\t\tevent.preventDefault();\r\n\t\tthis.Reveal.onUserInput();\r\n\r\n\t\tthis.Reveal.up();\r\n\r\n\t}\r\n\r\n\tonNavigateDownClicked( event ) {\r\n\r\n\t\tevent.preventDefault();\r\n\t\tthis.Reveal.onUserInput();\r\n\r\n\t\tthis.Reveal.down();\r\n\r\n\t}\r\n\r\n\tonNavigatePrevClicked( event ) {\r\n\r\n\t\tevent.preventDefault();\r\n\t\tthis.Reveal.onUserInput();\r\n\r\n\t\tthis.Reveal.prev();\r\n\r\n\t}\r\n\r\n\tonNavigateNextClicked( event ) {\r\n\r\n\t\tevent.preventDefault();\r\n\t\tthis.Reveal.onUserInput();\r\n\r\n\t\tthis.Reveal.next();\r\n\r\n\t}\r\n\r\n\tonEnterFullscreen( event ) {\r\n\r\n\t\tconst config = this.Reveal.getConfig();\r\n\t\tconst viewport = this.Reveal.getViewportElement();\r\n\r\n\t\tenterFullscreen( config.embedded ? viewport : viewport.parentElement );\r\n\r\n\t}\r\n\r\n}","/**\r\n * Creates a visual progress bar for the presentation.\r\n */\r\nexport default class Progress {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.onProgressClicked = this.onProgressClicked.bind( this );\r\n\r\n\t}\r\n\r\n\trender() {\r\n\r\n\t\tthis.element = document.createElement( 'div' );\r\n\t\tthis.element.className = 'progress';\r\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\r\n\r\n\t\tthis.bar = document.createElement( 'span' );\r\n\t\tthis.element.appendChild( this.bar );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tthis.element.style.display = config.progress ? 'block' : 'none';\r\n\r\n\t}\r\n\r\n\tbind() {\r\n\r\n\t\tif( this.Reveal.getConfig().progress && this.element ) {\r\n\t\t\tthis.element.addEventListener( 'click', this.onProgressClicked, false );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tunbind() {\r\n\r\n\t\tif ( this.Reveal.getConfig().progress && this.element ) {\r\n\t\t\tthis.element.removeEventListener( 'click', this.onProgressClicked, false );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the progress bar to reflect the current slide.\r\n\t */\r\n\tupdate() {\r\n\r\n\t\t// Update progress if enabled\r\n\t\tif( this.Reveal.getConfig().progress && this.bar ) {\r\n\r\n\t\t\tlet scale = this.Reveal.getProgress();\r\n\r\n\t\t\t// Don't fill the progress bar if there's only one slide\r\n\t\t\tif( this.Reveal.getTotalSlides() < 2 ) {\r\n\t\t\t\tscale = 0;\r\n\t\t\t}\r\n\r\n\t\t\tthis.bar.style.transform = 'scaleX('+ scale +')';\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tgetMaxWidth() {\r\n\r\n\t\treturn this.Reveal.getRevealElement().offsetWidth;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Clicking on the progress bar results in a navigation to the\r\n\t * closest approximate horizontal slide using this equation:\r\n\t *\r\n\t * ( clickX / presentationWidth ) * numberOfSlides\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonProgressClicked( event ) {\r\n\r\n\t\tthis.Reveal.onUserInput( event );\r\n\r\n\t\tevent.preventDefault();\r\n\r\n\t\tlet slides = this.Reveal.getSlides();\r\n\t\tlet slidesTotal = slides.length;\r\n\t\tlet slideIndex = Math.floor( ( event.clientX / this.getMaxWidth() ) * slidesTotal );\r\n\r\n\t\tif( this.Reveal.getConfig().rtl ) {\r\n\t\t\tslideIndex = slidesTotal - slideIndex;\r\n\t\t}\r\n\r\n\t\tlet targetIndices = this.Reveal.getIndices(slides[slideIndex]);\r\n\t\tthis.Reveal.slide( targetIndices.h, targetIndices.v );\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.element.remove();\r\n\r\n\t}\r\n\r\n}","/**\r\n * Handles hiding of the pointer/cursor when inactive.\r\n */\r\nexport default class Pointer {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\t// Throttles mouse wheel navigation\r\n\t\tthis.lastMouseWheelStep = 0;\r\n\r\n\t\t// Is the mouse pointer currently hidden from view\r\n\t\tthis.cursorHidden = false;\r\n\r\n\t\t// Timeout used to determine when the cursor is inactive\r\n\t\tthis.cursorInactiveTimeout = 0;\r\n\r\n\t\tthis.onDocumentCursorActive = this.onDocumentCursorActive.bind( this );\r\n\t\tthis.onDocumentMouseScroll = this.onDocumentMouseScroll.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tif( config.mouseWheel ) {\r\n\t\t\tdocument.addEventListener( 'wheel', this.onDocumentMouseScroll, false );\r\n\t\t}\r\n\t\telse {\r\n\t\t\tdocument.removeEventListener( 'wheel', this.onDocumentMouseScroll, false );\r\n\t\t}\r\n\r\n\t\t// Auto-hide the mouse pointer when its inactive\r\n\t\tif( config.hideInactiveCursor ) {\r\n\t\t\tdocument.addEventListener( 'mousemove', this.onDocumentCursorActive, false );\r\n\t\t\tdocument.addEventListener( 'mousedown', this.onDocumentCursorActive, false );\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.showCursor();\r\n\r\n\t\t\tdocument.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );\r\n\t\t\tdocument.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Shows the mouse pointer after it has been hidden with\r\n\t * #hideCursor.\r\n\t */\r\n\tshowCursor() {\r\n\r\n\t\tif( this.cursorHidden ) {\r\n\t\t\tthis.cursorHidden = false;\r\n\t\t\tthis.Reveal.getRevealElement().style.cursor = '';\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Hides the mouse pointer when it's on top of the .reveal\r\n\t * container.\r\n\t */\r\n\thideCursor() {\r\n\r\n\t\tif( this.cursorHidden === false ) {\r\n\t\t\tthis.cursorHidden = true;\r\n\t\t\tthis.Reveal.getRevealElement().style.cursor = 'none';\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.showCursor();\r\n\r\n\t\tdocument.removeEventListener( 'wheel', this.onDocumentMouseScroll, false );\r\n\t\tdocument.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );\r\n\t\tdocument.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called whenever there is mouse input at the document level\r\n\t * to determine if the cursor is active or not.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonDocumentCursorActive( event ) {\r\n\r\n\t\tthis.showCursor();\r\n\r\n\t\tclearTimeout( this.cursorInactiveTimeout );\r\n\r\n\t\tthis.cursorInactiveTimeout = setTimeout( this.hideCursor.bind( this ), this.Reveal.getConfig().hideCursorTime );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Handles mouse wheel scrolling, throttled to avoid skipping\r\n\t * multiple slides.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonDocumentMouseScroll( event ) {\r\n\r\n\t\tif( Date.now() - this.lastMouseWheelStep > 1000 ) {\r\n\r\n\t\t\tthis.lastMouseWheelStep = Date.now();\r\n\r\n\t\t\tlet delta = event.detail || -event.wheelDelta;\r\n\t\t\tif( delta > 0 ) {\r\n\t\t\t\tthis.Reveal.next();\r\n\t\t\t}\r\n\t\t\telse if( delta < 0 ) {\r\n\t\t\t\tthis.Reveal.prev();\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n","/**\r\n * Loads a JavaScript file from the given URL and executes it.\r\n *\r\n * @param {string} url Address of the .js file to load\r\n * @param {function} callback Method to invoke when the script\r\n * has loaded and executed\r\n */\r\nexport const loadScript = ( url, callback ) => {\r\n\r\n\tconst script = document.createElement( 'script' );\r\n\tscript.type = 'text/javascript';\r\n\tscript.async = false;\r\n\tscript.defer = false;\r\n\tscript.src = url;\r\n\r\n\tif( typeof callback === 'function' ) {\r\n\r\n\t\t// Success callback\r\n\t\tscript.onload = script.onreadystatechange = event => {\r\n\t\t\tif( event.type === 'load' || /loaded|complete/.test( script.readyState ) ) {\r\n\r\n\t\t\t\t// Kill event listeners\r\n\t\t\t\tscript.onload = script.onreadystatechange = script.onerror = null;\r\n\r\n\t\t\t\tcallback();\r\n\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\t// Error callback\r\n\t\tscript.onerror = err => {\r\n\r\n\t\t\t// Kill event listeners\r\n\t\t\tscript.onload = script.onreadystatechange = script.onerror = null;\r\n\r\n\t\t\tcallback( new Error( 'Failed loading script: ' + script.src + '\\n' + err ) );\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t// Append the script at the end of \r\n\tconst head = document.querySelector( 'head' );\r\n\thead.insertBefore( script, head.lastChild );\r\n\r\n}","import { loadScript } from '../utils/loader.js'\r\n\r\n/**\r\n * Manages loading and registering of reveal.js plugins.\r\n */\r\nexport default class Plugins {\r\n\r\n\tconstructor( reveal ) {\r\n\r\n\t\tthis.Reveal = reveal;\r\n\r\n\t\t// Flags our current state (idle -> loading -> loaded)\r\n\t\tthis.state = 'idle';\r\n\r\n\t\t// An id:instance map of currently registered plugins\r\n\t\tthis.registeredPlugins = {};\r\n\r\n\t\tthis.asyncDependencies = [];\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Loads reveal.js dependencies, registers and\r\n\t * initializes plugins.\r\n\t *\r\n\t * Plugins are direct references to a reveal.js plugin\r\n\t * object that we register and initialize after any\r\n\t * synchronous dependencies have loaded.\r\n\t *\r\n\t * Dependencies are defined via the 'dependencies' config\r\n\t * option and will be loaded prior to starting reveal.js.\r\n\t * Some dependencies may have an 'async' flag, if so they\r\n\t * will load after reveal.js has been started up.\r\n\t */\r\n\tload( plugins, dependencies ) {\r\n\r\n\t\tthis.state = 'loading';\r\n\r\n\t\tplugins.forEach( this.registerPlugin.bind( this ) );\r\n\r\n\t\treturn new Promise( resolve => {\r\n\r\n\t\t\tlet scripts = [],\r\n\t\t\t\tscriptsToLoad = 0;\r\n\r\n\t\t\tdependencies.forEach( s => {\r\n\t\t\t\t// Load if there's no condition or the condition is truthy\r\n\t\t\t\tif( !s.condition || s.condition() ) {\r\n\t\t\t\t\tif( s.async ) {\r\n\t\t\t\t\t\tthis.asyncDependencies.push( s );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tscripts.push( s );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} );\r\n\r\n\t\t\tif( scripts.length ) {\r\n\t\t\t\tscriptsToLoad = scripts.length;\r\n\r\n\t\t\t\tconst scriptLoadedCallback = (s) => {\r\n\t\t\t\t\tif( s && typeof s.callback === 'function' ) s.callback();\r\n\r\n\t\t\t\t\tif( --scriptsToLoad === 0 ) {\r\n\t\t\t\t\t\tthis.initPlugins().then( resolve );\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// Load synchronous scripts\r\n\t\t\t\tscripts.forEach( s => {\r\n\t\t\t\t\tif( typeof s.id === 'string' ) {\r\n\t\t\t\t\t\tthis.registerPlugin( s );\r\n\t\t\t\t\t\tscriptLoadedCallback( s );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if( typeof s.src === 'string' ) {\r\n\t\t\t\t\t\tloadScript( s.src, () => scriptLoadedCallback(s) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tconsole.warn( 'Unrecognized plugin format', s );\r\n\t\t\t\t\t\tscriptLoadedCallback();\r\n\t\t\t\t\t}\r\n\t\t\t\t} );\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tthis.initPlugins().then( resolve );\r\n\t\t\t}\r\n\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Initializes our plugins and waits for them to be ready\r\n\t * before proceeding.\r\n\t */\r\n\tinitPlugins() {\r\n\r\n\t\treturn new Promise( resolve => {\r\n\r\n\t\t\tlet pluginValues = Object.values( this.registeredPlugins );\r\n\t\t\tlet pluginsToInitialize = pluginValues.length;\r\n\r\n\t\t\t// If there are no plugins, skip this step\r\n\t\t\tif( pluginsToInitialize === 0 ) {\r\n\t\t\t\tthis.loadAsync().then( resolve );\r\n\t\t\t}\r\n\t\t\t// ... otherwise initialize plugins\r\n\t\t\telse {\r\n\r\n\t\t\t\tlet initNextPlugin;\r\n\r\n\t\t\t\tlet afterPlugInitialized = () => {\r\n\t\t\t\t\tif( --pluginsToInitialize === 0 ) {\r\n\t\t\t\t\t\tthis.loadAsync().then( resolve );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tinitNextPlugin();\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\tlet i = 0;\r\n\r\n\t\t\t\t// Initialize plugins serially\r\n\t\t\t\tinitNextPlugin = () => {\r\n\r\n\t\t\t\t\tlet plugin = pluginValues[i++];\r\n\r\n\t\t\t\t\t// If the plugin has an 'init' method, invoke it\r\n\t\t\t\t\tif( typeof plugin.init === 'function' ) {\r\n\t\t\t\t\t\tlet promise = plugin.init( this.Reveal );\r\n\r\n\t\t\t\t\t\t// If the plugin returned a Promise, wait for it\r\n\t\t\t\t\t\tif( promise && typeof promise.then === 'function' ) {\r\n\t\t\t\t\t\t\tpromise.then( afterPlugInitialized );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\tafterPlugInitialized();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tafterPlugInitialized();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tinitNextPlugin();\r\n\r\n\t\t\t}\r\n\r\n\t\t} )\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Loads all async reveal.js dependencies.\r\n\t */\r\n\tloadAsync() {\r\n\r\n\t\tthis.state = 'loaded';\r\n\r\n\t\tif( this.asyncDependencies.length ) {\r\n\t\t\tthis.asyncDependencies.forEach( s => {\r\n\t\t\t\tloadScript( s.src, s.callback );\r\n\t\t\t} );\r\n\t\t}\r\n\r\n\t\treturn Promise.resolve();\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Registers a new plugin with this reveal.js instance.\r\n\t *\r\n\t * reveal.js waits for all registered plugins to initialize\r\n\t * before considering itself ready, as long as the plugin\r\n\t * is registered before calling `Reveal.initialize()`.\r\n\t */\r\n\tregisterPlugin( plugin ) {\r\n\r\n\t\t// Backwards compatibility to make reveal.js ~3.9.0\r\n\t\t// plugins work with reveal.js 4.0.0\r\n\t\tif( arguments.length === 2 && typeof arguments[0] === 'string' ) {\r\n\t\t\tplugin = arguments[1];\r\n\t\t\tplugin.id = arguments[0];\r\n\t\t}\r\n\t\t// Plugin can optionally be a function which we call\r\n\t\t// to create an instance of the plugin\r\n\t\telse if( typeof plugin === 'function' ) {\r\n\t\t\tplugin = plugin();\r\n\t\t}\r\n\r\n\t\tlet id = plugin.id;\r\n\r\n\t\tif( typeof id !== 'string' ) {\r\n\t\t\tconsole.warn( 'Unrecognized plugin format; can\\'t find plugin.id', plugin );\r\n\t\t}\r\n\t\telse if( this.registeredPlugins[id] === undefined ) {\r\n\t\t\tthis.registeredPlugins[id] = plugin;\r\n\r\n\t\t\t// If a plugin is registered after reveal.js is loaded,\r\n\t\t\t// initialize it right away\r\n\t\t\tif( this.state === 'loaded' && typeof plugin.init === 'function' ) {\r\n\t\t\t\tplugin.init( this.Reveal );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\tconsole.warn( 'reveal.js: \"'+ id +'\" plugin has already been registered' );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if a specific plugin has been registered.\r\n\t *\r\n\t * @param {String} id Unique plugin identifier\r\n\t */\r\n\thasPlugin( id ) {\r\n\r\n\t\treturn !!this.registeredPlugins[id];\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the specific plugin instance, if a plugin\r\n\t * with the given ID has been registered.\r\n\t *\r\n\t * @param {String} id Unique plugin identifier\r\n\t */\r\n\tgetPlugin( id ) {\r\n\r\n\t\treturn this.registeredPlugins[id];\r\n\r\n\t}\r\n\r\n\tgetRegisteredPlugins() {\r\n\r\n\t\treturn this.registeredPlugins;\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tObject.values( this.registeredPlugins ).forEach( plugin => {\r\n\t\t\tif( typeof plugin.destroy === 'function' ) {\r\n\t\t\t\tplugin.destroy();\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.registeredPlugins = {};\r\n\t\tthis.asyncDependencies = [];\r\n\r\n\t}\r\n\r\n}\r\n","import { isAndroid } from '../utils/device.js'\r\nimport { matches } from '../utils/util.js'\r\n\r\nconst SWIPE_THRESHOLD = 40;\r\n\r\n/**\r\n * Controls all touch interactions and navigations for\r\n * a presentation.\r\n */\r\nexport default class Touch {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\t// Holds information about the currently ongoing touch interaction\r\n\t\tthis.touchStartX = 0;\r\n\t\tthis.touchStartY = 0;\r\n\t\tthis.touchStartCount = 0;\r\n\t\tthis.touchCaptured = false;\r\n\r\n\t\tthis.onPointerDown = this.onPointerDown.bind( this );\r\n\t\tthis.onPointerMove = this.onPointerMove.bind( this );\r\n\t\tthis.onPointerUp = this.onPointerUp.bind( this );\r\n\t\tthis.onTouchStart = this.onTouchStart.bind( this );\r\n\t\tthis.onTouchMove = this.onTouchMove.bind( this );\r\n\t\tthis.onTouchEnd = this.onTouchEnd.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t *\r\n\t */\r\n\tbind() {\r\n\r\n\t\tlet revealElement = this.Reveal.getRevealElement();\r\n\r\n\t\tif( 'onpointerdown' in window ) {\r\n\t\t\t// Use W3C pointer events\r\n\t\t\trevealElement.addEventListener( 'pointerdown', this.onPointerDown, false );\r\n\t\t\trevealElement.addEventListener( 'pointermove', this.onPointerMove, false );\r\n\t\t\trevealElement.addEventListener( 'pointerup', this.onPointerUp, false );\r\n\t\t}\r\n\t\telse if( window.navigator.msPointerEnabled ) {\r\n\t\t\t// IE 10 uses prefixed version of pointer events\r\n\t\t\trevealElement.addEventListener( 'MSPointerDown', this.onPointerDown, false );\r\n\t\t\trevealElement.addEventListener( 'MSPointerMove', this.onPointerMove, false );\r\n\t\t\trevealElement.addEventListener( 'MSPointerUp', this.onPointerUp, false );\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// Fall back to touch events\r\n\t\t\trevealElement.addEventListener( 'touchstart', this.onTouchStart, false );\r\n\t\t\trevealElement.addEventListener( 'touchmove', this.onTouchMove, false );\r\n\t\t\trevealElement.addEventListener( 'touchend', this.onTouchEnd, false );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t *\r\n\t */\r\n\tunbind() {\r\n\r\n\t\tlet revealElement = this.Reveal.getRevealElement();\r\n\r\n\t\trevealElement.removeEventListener( 'pointerdown', this.onPointerDown, false );\r\n\t\trevealElement.removeEventListener( 'pointermove', this.onPointerMove, false );\r\n\t\trevealElement.removeEventListener( 'pointerup', this.onPointerUp, false );\r\n\r\n\t\trevealElement.removeEventListener( 'MSPointerDown', this.onPointerDown, false );\r\n\t\trevealElement.removeEventListener( 'MSPointerMove', this.onPointerMove, false );\r\n\t\trevealElement.removeEventListener( 'MSPointerUp', this.onPointerUp, false );\r\n\r\n\t\trevealElement.removeEventListener( 'touchstart', this.onTouchStart, false );\r\n\t\trevealElement.removeEventListener( 'touchmove', this.onTouchMove, false );\r\n\t\trevealElement.removeEventListener( 'touchend', this.onTouchEnd, false );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if the target element prevents the triggering of\r\n\t * swipe navigation.\r\n\t */\r\n\tisSwipePrevented( target ) {\r\n\r\n\t\t// Prevent accidental swipes when scrubbing timelines\r\n\t\tif( matches( target, 'video, audio' ) ) return true;\r\n\r\n\t\twhile( target && typeof target.hasAttribute === 'function' ) {\r\n\t\t\tif( target.hasAttribute( 'data-prevent-swipe' ) ) return true;\r\n\t\t\ttarget = target.parentNode;\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Handler for the 'touchstart' event, enables support for\r\n\t * swipe and pinch gestures.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonTouchStart( event ) {\r\n\r\n\t\tif( this.isSwipePrevented( event.target ) ) return true;\r\n\r\n\t\tthis.touchStartX = event.touches[0].clientX;\r\n\t\tthis.touchStartY = event.touches[0].clientY;\r\n\t\tthis.touchStartCount = event.touches.length;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Handler for the 'touchmove' event.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonTouchMove( event ) {\r\n\r\n\t\tif( this.isSwipePrevented( event.target ) ) return true;\r\n\r\n\t\tlet config = this.Reveal.getConfig();\r\n\r\n\t\t// Each touch should only trigger one action\r\n\t\tif( !this.touchCaptured ) {\r\n\t\t\tthis.Reveal.onUserInput( event );\r\n\r\n\t\t\tlet currentX = event.touches[0].clientX;\r\n\t\t\tlet currentY = event.touches[0].clientY;\r\n\r\n\t\t\t// There was only one touch point, look for a swipe\r\n\t\t\tif( event.touches.length === 1 && this.touchStartCount !== 2 ) {\r\n\r\n\t\t\t\tlet availableRoutes = this.Reveal.availableRoutes({ includeFragments: true });\r\n\r\n\t\t\t\tlet deltaX = currentX - this.touchStartX,\r\n\t\t\t\t\tdeltaY = currentY - this.touchStartY;\r\n\r\n\t\t\t\tif( deltaX > SWIPE_THRESHOLD && Math.abs( deltaX ) > Math.abs( deltaY ) ) {\r\n\t\t\t\t\tthis.touchCaptured = true;\r\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\r\n\t\t\t\t\t\tif( config.rtl ) {\r\n\t\t\t\t\t\t\tthis.Reveal.next();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\tthis.Reveal.prev();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tthis.Reveal.left();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse if( deltaX < -SWIPE_THRESHOLD && Math.abs( deltaX ) > Math.abs( deltaY ) ) {\r\n\t\t\t\t\tthis.touchCaptured = true;\r\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\r\n\t\t\t\t\t\tif( config.rtl ) {\r\n\t\t\t\t\t\t\tthis.Reveal.prev();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse {\r\n\t\t\t\t\t\t\tthis.Reveal.next();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tthis.Reveal.right();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse if( deltaY > SWIPE_THRESHOLD && availableRoutes.up ) {\r\n\t\t\t\t\tthis.touchCaptured = true;\r\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\r\n\t\t\t\t\t\tthis.Reveal.prev();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tthis.Reveal.up();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse if( deltaY < -SWIPE_THRESHOLD && availableRoutes.down ) {\r\n\t\t\t\t\tthis.touchCaptured = true;\r\n\t\t\t\t\tif( config.navigationMode === 'linear' ) {\r\n\t\t\t\t\t\tthis.Reveal.next();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse {\r\n\t\t\t\t\t\tthis.Reveal.down();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// If we're embedded, only block touch events if they have\r\n\t\t\t\t// triggered an action\r\n\t\t\t\tif( config.embedded ) {\r\n\t\t\t\t\tif( this.touchCaptured || this.Reveal.isVerticalSlide() ) {\r\n\t\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// Not embedded? Block them all to avoid needless tossing\r\n\t\t\t\t// around of the viewport in iOS\r\n\t\t\t\telse {\r\n\t\t\t\t\tevent.preventDefault();\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\t\t}\r\n\t\t// There's a bug with swiping on some Android devices unless\r\n\t\t// the default action is always prevented\r\n\t\telse if( isAndroid ) {\r\n\t\t\tevent.preventDefault();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Handler for the 'touchend' event.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonTouchEnd( event ) {\r\n\r\n\t\tthis.touchCaptured = false;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Convert pointer down to touch start.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonPointerDown( event ) {\r\n\r\n\t\tif( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === \"touch\" ) {\r\n\t\t\tevent.touches = [{ clientX: event.clientX, clientY: event.clientY }];\r\n\t\t\tthis.onTouchStart( event );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Convert pointer move to touch move.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonPointerMove( event ) {\r\n\r\n\t\tif( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === \"touch\" ) {\r\n\t\t\tevent.touches = [{ clientX: event.clientX, clientY: event.clientY }];\r\n\t\t\tthis.onTouchMove( event );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Convert pointer up to touch end.\r\n\t *\r\n\t * @param {object} event\r\n\t */\r\n\tonPointerUp( event ) {\r\n\r\n\t\tif( event.pointerType === event.MSPOINTER_TYPE_TOUCH || event.pointerType === \"touch\" ) {\r\n\t\t\tevent.touches = [{ clientX: event.clientX, clientY: event.clientY }];\r\n\t\t\tthis.onTouchEnd( event );\r\n\t\t}\r\n\r\n\t}\r\n\r\n}","import { closest } from '../utils/util.js'\r\n\r\n/**\r\n * Manages focus when a presentation is embedded. This\r\n * helps us only capture keyboard from the presentation\r\n * a user is currently interacting with in a page where\r\n * multiple presentations are embedded.\r\n */\r\n\r\nconst STATE_FOCUS = 'focus';\r\nconst STATE_BLUR = 'blur';\r\n\r\nexport default class Focus {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t\tthis.onRevealPointerDown = this.onRevealPointerDown.bind( this );\r\n\t\tthis.onDocumentPointerDown = this.onDocumentPointerDown.bind( this );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tif( config.embedded ) {\r\n\t\t\tthis.blur();\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.focus();\r\n\t\t\tthis.unbind();\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tbind() {\r\n\r\n\t\tif( this.Reveal.getConfig().embedded ) {\r\n\t\t\tthis.Reveal.getRevealElement().addEventListener( 'pointerdown', this.onRevealPointerDown, false );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tunbind() {\r\n\r\n\t\tthis.Reveal.getRevealElement().removeEventListener( 'pointerdown', this.onRevealPointerDown, false );\r\n\t\tdocument.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );\r\n\r\n\t}\r\n\r\n\tfocus() {\r\n\r\n\t\tif( this.state !== STATE_FOCUS ) {\r\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'focused' );\r\n\t\t\tdocument.addEventListener( 'pointerdown', this.onDocumentPointerDown, false );\r\n\t\t}\r\n\r\n\t\tthis.state = STATE_FOCUS;\r\n\r\n\t}\r\n\r\n\tblur() {\r\n\r\n\t\tif( this.state !== STATE_BLUR ) {\r\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'focused' );\r\n\t\t\tdocument.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );\r\n\t\t}\r\n\r\n\t\tthis.state = STATE_BLUR;\r\n\r\n\t}\r\n\r\n\tisFocused() {\r\n\r\n\t\treturn this.state === STATE_FOCUS;\r\n\r\n\t}\r\n\r\n\tdestroy() {\r\n\r\n\t\tthis.Reveal.getRevealElement().classList.remove( 'focused' );\r\n\r\n\t}\r\n\r\n\tonRevealPointerDown( event ) {\r\n\r\n\t\tthis.focus();\r\n\r\n\t}\r\n\r\n\tonDocumentPointerDown( event ) {\r\n\r\n\t\tlet revealElement = closest( event.target, '.reveal' );\r\n\t\tif( !revealElement || revealElement !== this.Reveal.getRevealElement() ) {\r\n\t\t\tthis.blur();\r\n\t\t}\r\n\r\n\t}\r\n\r\n}","/**\r\n * Handles the showing of speaker notes\r\n */\r\nexport default class Notes {\r\n\r\n\tconstructor( Reveal ) {\r\n\r\n\t\tthis.Reveal = Reveal;\r\n\r\n\t}\r\n\r\n\trender() {\r\n\r\n\t\tthis.element = document.createElement( 'div' );\r\n\t\tthis.element.className = 'speaker-notes';\r\n\t\tthis.element.setAttribute( 'data-prevent-swipe', '' );\r\n\t\tthis.element.setAttribute( 'tabindex', '0' );\r\n\t\tthis.Reveal.getRevealElement().appendChild( this.element );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Called when the reveal.js config is updated.\r\n\t */\r\n\tconfigure( config, oldConfig ) {\r\n\r\n\t\tif( config.showNotes ) {\r\n\t\t\tthis.element.setAttribute( 'data-layout', typeof config.showNotes === 'string' ? config.showNotes : 'inline' );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Pick up notes from the current slide and display them\r\n\t * to the viewer.\r\n\t *\r\n\t * @see {@link config.showNotes}\r\n\t */\r\n\tupdate() {\r\n\r\n\t\tif( this.Reveal.getConfig().showNotes &&\r\n\t\t\tthis.element && this.Reveal.getCurrentSlide() &&\r\n\t\t\t!this.Reveal.isScrollView() &&\r\n\t\t\t!this.Reveal.isPrintView()\r\n\t\t) {\r\n\t\t\tthis.element.innerHTML = this.getSlideNotes() || 'No notes on this slide.';\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the visibility of the speaker notes sidebar that\r\n\t * is used to share annotated slides. The notes sidebar is\r\n\t * only visible if showNotes is true and there are notes on\r\n\t * one or more slides in the deck.\r\n\t */\r\n\tupdateVisibility() {\r\n\r\n\t\tif( this.Reveal.getConfig().showNotes &&\r\n\t\t\tthis.hasNotes() &&\r\n\t\t\t!this.Reveal.isScrollView() &&\r\n\t\t\t!this.Reveal.isPrintView()\r\n\t\t) {\r\n\t\t\tthis.Reveal.getRevealElement().classList.add( 'show-notes' );\r\n\t\t}\r\n\t\telse {\r\n\t\t\tthis.Reveal.getRevealElement().classList.remove( 'show-notes' );\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if there are speaker notes for ANY slide in the\r\n\t * presentation.\r\n\t */\r\n\thasNotes() {\r\n\r\n\t\treturn this.Reveal.getSlidesElement().querySelectorAll( '[data-notes], aside.notes' ).length > 0;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Checks if this presentation is running inside of the\r\n\t * speaker notes window.\r\n\t *\r\n\t * @return {boolean}\r\n\t */\r\n\tisSpeakerNotesWindow() {\r\n\r\n\t\treturn !!window.location.search.match( /receiver/gi );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Retrieves the speaker notes from a slide. Notes can be\r\n\t * defined in two ways:\r\n\t * 1. As a data-notes attribute on the slide
\r\n\t * 2. With