├── index.ts ├── docs ├── _config.yml ├── twine.8d2749c5.jpeg ├── wireframe1.8b04f7a4.png ├── wireframe2.975e1496.png ├── wireframe3.3b391139.png ├── Robert_Kurvitz.1e071ecb.png ├── disco-elysium.505f25b2.jpeg ├── favicon-16x16.c185778f.png ├── favicon-32x32.3df3657b.png ├── the-real-twine.4ec6a6c5.png ├── wireframe-blank.7d2bb3fd.jpg ├── apple-touch-icon.968a9f06.png ├── wireframe-mockup.83fef09e.jpg ├── slides.f84e1103.js.map ├── android-chrome-192x192.678466e6.png ├── android-chrome-256x256.29e071d4.png ├── source-sans-pro-italic.0f120925.eot ├── source-sans-pro-italic.5d4a526c.ttf ├── source-sans-pro-italic.2b368cd4.woff ├── source-sans-pro-regular.1d0dc635.ttf ├── source-sans-pro-regular.8c0dfd96.woff ├── source-sans-pro-regular.9ac2c485.eot ├── source-sans-pro-semibold.7404e447.eot ├── source-sans-pro-semibold.a9b87e73.woff ├── source-sans-pro-semibold.e3ba0356.ttf ├── source-sans-pro-semibolditalic.182cbf53.eot ├── source-sans-pro-semibolditalic.cb994017.ttf ├── source-sans-pro-semibolditalic.399924e3.woff ├── meta │ └── site.webmanifest ├── main.98ba66d6.css ├── main.98ba66d6.css.map ├── slides.f84e1103.js ├── safari-pinned-tab.ead9fee4.svg ├── index.html └── slides │ └── disco-prelysium │ └── index.html ├── .nvmrc ├── .sassrc ├── meta ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-256x256.png ├── android-chrome-512x512.png ├── site.webmanifest └── safari-pinned-tab.svg ├── scss ├── fonts │ ├── league-gothic │ │ ├── LICENSE │ │ ├── league-gothic.eot │ │ ├── league-gothic.ttf │ │ ├── league-gothic.woff │ │ └── league-gothic.css │ └── source-sans-pro │ │ ├── source-sans-pro-italic.eot │ │ ├── source-sans-pro-italic.ttf │ │ ├── source-sans-pro-italic.woff │ │ ├── source-sans-pro-regular.eot │ │ ├── source-sans-pro-regular.ttf │ │ ├── source-sans-pro-regular.woff │ │ ├── source-sans-pro-semibold.eot │ │ ├── source-sans-pro-semibold.ttf │ │ ├── source-sans-pro-semibold.woff │ │ ├── source-sans-pro-semibolditalic.eot │ │ ├── source-sans-pro-semibolditalic.ttf │ │ ├── source-sans-pro-semibolditalic.woff │ │ ├── source-sans-pro.css │ │ └── LICENSE ├── main.scss ├── theme │ ├── source │ │ ├── fonts │ │ │ ├── league-gothic │ │ │ │ ├── LICENSE │ │ │ │ ├── league-gothic.eot │ │ │ │ ├── league-gothic.ttf │ │ │ │ ├── league-gothic.woff │ │ │ │ └── league-gothic.css │ │ │ └── source-sans-pro │ │ │ │ ├── source-sans-pro-italic.eot │ │ │ │ ├── source-sans-pro-italic.ttf │ │ │ │ ├── source-sans-pro-italic.woff │ │ │ │ ├── source-sans-pro-regular.eot │ │ │ │ ├── source-sans-pro-regular.ttf │ │ │ │ ├── source-sans-pro-regular.woff │ │ │ │ ├── source-sans-pro-semibold.eot │ │ │ │ ├── source-sans-pro-semibold.ttf │ │ │ │ ├── source-sans-pro-semibold.woff │ │ │ │ ├── source-sans-pro-semibolditalic.eot │ │ │ │ ├── source-sans-pro-semibolditalic.ttf │ │ │ │ ├── source-sans-pro-semibolditalic.woff │ │ │ │ ├── source-sans-pro.css │ │ │ │ └── LICENSE │ │ ├── night.scss │ │ ├── serif.scss │ │ ├── league.scss │ │ ├── white.scss │ │ ├── black.scss │ │ ├── simple.scss │ │ ├── sky.scss │ │ ├── beige.scss │ │ ├── moon.scss │ │ ├── solarized.scss │ │ └── blood.scss │ ├── template │ │ ├── exposer.scss │ │ ├── settings.scss │ │ ├── mixins.scss │ │ └── theme.scss │ └── README.md ├── reset.scss ├── layout.scss └── print │ ├── pdf.scss │ └── paper.scss ├── slides └── disco-prelysium │ ├── assets │ ├── twine.jpeg │ ├── wireframe1.png │ ├── wireframe2.png │ ├── wireframe3.png │ ├── wireframes.jpg │ ├── Robert_Kurvitz.png │ ├── disco-elysium.jpeg │ ├── the-real-twine.png │ ├── wireframe-blank.jpg │ └── wireframe-mockup.jpg │ ├── index.ts │ ├── main.scss │ └── index.html ├── Makefile ├── README.md ├── package.json ├── LICENSE ├── js ├── highlight │ ├── monokai.css │ ├── zenburn.css │ └── plugin.js ├── math │ ├── math.esm.js │ ├── math.js │ └── plugin.js ├── zoom │ ├── zoom.esm.js │ ├── zoom.js │ └── plugin.js ├── notes │ └── plugin.js ├── search │ ├── plugin.js │ ├── search.esm.js │ └── search.js └── markdown │ └── plugin.js ├── index.html └── .gitignore /index.ts: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v14.10.1 2 | -------------------------------------------------------------------------------- /.sassrc: -------------------------------------------------------------------------------- 1 | { 2 | "includePaths": ["node_modules"] 3 | } -------------------------------------------------------------------------------- /meta/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/favicon.ico -------------------------------------------------------------------------------- /meta/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/favicon-16x16.png -------------------------------------------------------------------------------- /meta/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/favicon-32x32.png -------------------------------------------------------------------------------- /docs/twine.8d2749c5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/twine.8d2749c5.jpeg -------------------------------------------------------------------------------- /meta/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/wireframe1.8b04f7a4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/wireframe1.8b04f7a4.png -------------------------------------------------------------------------------- /docs/wireframe2.975e1496.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/wireframe2.975e1496.png -------------------------------------------------------------------------------- /docs/wireframe3.3b391139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/wireframe3.3b391139.png -------------------------------------------------------------------------------- /docs/Robert_Kurvitz.1e071ecb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/Robert_Kurvitz.1e071ecb.png -------------------------------------------------------------------------------- /docs/disco-elysium.505f25b2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/disco-elysium.505f25b2.jpeg -------------------------------------------------------------------------------- /docs/favicon-16x16.c185778f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/favicon-16x16.c185778f.png -------------------------------------------------------------------------------- /docs/favicon-32x32.3df3657b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/favicon-32x32.3df3657b.png -------------------------------------------------------------------------------- /docs/the-real-twine.4ec6a6c5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/the-real-twine.4ec6a6c5.png -------------------------------------------------------------------------------- /docs/wireframe-blank.7d2bb3fd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/wireframe-blank.7d2bb3fd.jpg -------------------------------------------------------------------------------- /meta/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/android-chrome-192x192.png -------------------------------------------------------------------------------- /meta/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/android-chrome-256x256.png -------------------------------------------------------------------------------- /meta/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/meta/android-chrome-512x512.png -------------------------------------------------------------------------------- /docs/apple-touch-icon.968a9f06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/apple-touch-icon.968a9f06.png -------------------------------------------------------------------------------- /docs/wireframe-mockup.83fef09e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/wireframe-mockup.83fef09e.jpg -------------------------------------------------------------------------------- /docs/slides.f84e1103.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"slides.f84e1103.js","sourceRoot":".."} -------------------------------------------------------------------------------- /docs/android-chrome-192x192.678466e6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/android-chrome-192x192.678466e6.png -------------------------------------------------------------------------------- /docs/android-chrome-256x256.29e071d4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/android-chrome-256x256.29e071d4.png -------------------------------------------------------------------------------- /docs/source-sans-pro-italic.0f120925.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-italic.0f120925.eot -------------------------------------------------------------------------------- /docs/source-sans-pro-italic.5d4a526c.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-italic.5d4a526c.ttf -------------------------------------------------------------------------------- /scss/fonts/league-gothic/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License (OFL) 2 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 3 | -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/twine.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/twine.jpeg -------------------------------------------------------------------------------- /docs/source-sans-pro-italic.2b368cd4.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-italic.2b368cd4.woff -------------------------------------------------------------------------------- /docs/source-sans-pro-regular.1d0dc635.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-regular.1d0dc635.ttf -------------------------------------------------------------------------------- /docs/source-sans-pro-regular.8c0dfd96.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-regular.8c0dfd96.woff -------------------------------------------------------------------------------- /docs/source-sans-pro-regular.9ac2c485.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-regular.9ac2c485.eot -------------------------------------------------------------------------------- /docs/source-sans-pro-semibold.7404e447.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-semibold.7404e447.eot -------------------------------------------------------------------------------- /docs/source-sans-pro-semibold.a9b87e73.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-semibold.a9b87e73.woff -------------------------------------------------------------------------------- /docs/source-sans-pro-semibold.e3ba0356.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-semibold.e3ba0356.ttf -------------------------------------------------------------------------------- /scss/fonts/league-gothic/league-gothic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/league-gothic/league-gothic.eot -------------------------------------------------------------------------------- /scss/fonts/league-gothic/league-gothic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/league-gothic/league-gothic.ttf -------------------------------------------------------------------------------- /scss/fonts/league-gothic/league-gothic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/league-gothic/league-gothic.woff -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/wireframe1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/wireframe1.png -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/wireframe2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/wireframe2.png -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/wireframe3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/wireframe3.png -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/wireframes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/wireframes.jpg -------------------------------------------------------------------------------- /docs/source-sans-pro-semibolditalic.182cbf53.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-semibolditalic.182cbf53.eot -------------------------------------------------------------------------------- /docs/source-sans-pro-semibolditalic.cb994017.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-semibolditalic.cb994017.ttf -------------------------------------------------------------------------------- /scss/main.scss: -------------------------------------------------------------------------------- 1 | @import 'reset.scss'; 2 | @import 'reveal.scss'; 3 | @import 'theme/source/black.scss'; 4 | @import '../js/highlight/monokai.css'; -------------------------------------------------------------------------------- /scss/theme/source/fonts/league-gothic/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License (OFL) 2 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 3 | -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/Robert_Kurvitz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/Robert_Kurvitz.png -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/disco-elysium.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/disco-elysium.jpeg -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/the-real-twine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/the-real-twine.png -------------------------------------------------------------------------------- /docs/source-sans-pro-semibolditalic.399924e3.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/docs/source-sans-pro-semibolditalic.399924e3.woff -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/wireframe-blank.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/wireframe-blank.jpg -------------------------------------------------------------------------------- /slides/disco-prelysium/assets/wireframe-mockup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/slides/disco-prelysium/assets/wireframe-mockup.jpg -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-italic.eot -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-italic.ttf -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-italic.woff -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-regular.eot -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-regular.ttf -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-regular.woff -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-semibold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-semibold.eot -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-semibold.ttf -------------------------------------------------------------------------------- /scss/theme/source/fonts/league-gothic/league-gothic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/league-gothic/league-gothic.eot -------------------------------------------------------------------------------- /scss/theme/source/fonts/league-gothic/league-gothic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/league-gothic/league-gothic.ttf -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-semibold.woff -------------------------------------------------------------------------------- /scss/theme/source/fonts/league-gothic/league-gothic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/league-gothic/league-gothic.woff -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: run dist 2 | 3 | dist: 4 | rm -rf docs/ 5 | mkdir -p docs 6 | touch docs/_config.yml 7 | npm run dist 8 | 9 | run: 10 | npm run start 11 | -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-italic.eot -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-italic.ttf -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-italic.woff -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-regular.eot -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-regular.ttf -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-regular.woff -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibold.eot -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibold.ttf -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibold.woff -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibolditalic.eot -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibolditalic.ttf -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juanuys/slides/master/scss/theme/source/fonts/source-sans-pro/source-sans-pro-semibolditalic.woff -------------------------------------------------------------------------------- /docs/meta/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"android-chrome-192x192.678466e6.png","sizes":"192x192","type":"image/png"},{"src":"android-chrome-256x256.29e071d4.png","sizes":"256x256","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | Some of my slides. 4 | 5 | # Tech 6 | 7 | Dev/build: 8 | 9 | nvm use 10 | make run 11 | make dist 12 | 13 | In Github Pages settings, have it set to: 14 | 15 | > Your GitHub Pages site is currently being built from the /docs folder in the master branch. 16 | -------------------------------------------------------------------------------- /scss/fonts/league-gothic/league-gothic.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'League Gothic'; 3 | src: url('./league-gothic.eot'); 4 | src: url('./league-gothic.eot?#iefix') format('embedded-opentype'), 5 | url('./league-gothic.woff') format('woff'), 6 | url('./league-gothic.ttf') format('truetype'); 7 | 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | -------------------------------------------------------------------------------- /scss/theme/source/fonts/league-gothic/league-gothic.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'League Gothic'; 3 | src: url('./league-gothic.eot'); 4 | src: url('./league-gothic.eot?#iefix') format('embedded-opentype'), 5 | url('./league-gothic.woff') format('woff'), 6 | url('./league-gothic.ttf') format('truetype'); 7 | 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | -------------------------------------------------------------------------------- /docs/main.98ba66d6.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";ul.colourcoded li:before{content:"▇ "}ul.colourcoded li:first-child{color:orange}ul.colourcoded li:nth-child(2){color:purple}ul.colourcoded li:nth-child(3){color:#fff}ul.colourcoded.tiny{font-size:.5em}ul.colourcoded.tiny>*{display:inline-block}p.smalltext{font-size:.5em}p.smalltext:before{content:'"';font-size:2em}img{height:300px} 2 | /*# sourceMappingURL=https://juanuys.com/slides/main.98ba66d6.css.map */ -------------------------------------------------------------------------------- /meta/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/meta/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/meta/android-chrome-256x256.png", 12 | "sizes": "256x256", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /slides/disco-prelysium/index.ts: -------------------------------------------------------------------------------- 1 | import Reveal from "reveal.js" 2 | import RevealHighlight from "../../js/highlight/highlight" 3 | import RevealMarkdown from "../../js/markdown/markdown" 4 | import RevealNotes from "../../js/notes/notes" 5 | 6 | // More info about initialization & config: 7 | // - https://revealjs.com/initialization/ 8 | // - https://revealjs.com/config/ 9 | Reveal.initialize({ 10 | hash: true, 11 | 12 | // Learn about plugins: https://revealjs.com/plugins/ 13 | plugins: [RevealMarkdown, RevealHighlight, RevealNotes] 14 | }); -------------------------------------------------------------------------------- /slides/disco-prelysium/main.scss: -------------------------------------------------------------------------------- 1 | ul.colourcoded { 2 | li::before { 3 | content: "▇ "; 4 | } 5 | li:nth-child(1) { 6 | color: orange; 7 | } 8 | li:nth-child(2) { 9 | color: purple; 10 | } 11 | li:nth-child(3) { 12 | color: white; 13 | } 14 | 15 | &.tiny { 16 | font-size: 0.5em; 17 | &>* { 18 | display: inline-block; 19 | } 20 | } 21 | } 22 | 23 | p.smalltext { 24 | font-size: 0.5em; 25 | &::before { 26 | content: '"'; 27 | font-size: 2em; 28 | } 29 | } 30 | 31 | img { 32 | height: 300px; 33 | } -------------------------------------------------------------------------------- /docs/main.98ba66d6.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["slides/disco-prelysium/main.scss"],"names":[],"mappings":"AACI,iBAAA,yBACI,aAEJ,8BACI,aAEJ,+BACI,aAEJ,+BACI,WAGJ,oBACI,eACA,sBACI,qBAKZ,YACI,eACA,mBACI,WAAA,CACA,cAIR,IACI","file":"main.98ba66d6.css","sourceRoot":"..","sourcesContent":["ul.colourcoded {\n li::before {\n content: \"▇ \";\n }\n li:nth-child(1) {\n color: orange;\n }\n li:nth-child(2) {\n color: purple;\n }\n li:nth-child(3) {\n color: white;\n }\n\n &.tiny {\n font-size: 0.5em;\n &>* {\n display: inline-block;\n }\n }\n}\n\np.smalltext {\n font-size: 0.5em;\n &::before {\n content: '\"';\n font-size: 2em;\n }\n}\n\nimg {\n height: 300px;\n}"]} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "slides", 3 | "version": "0.0.1", 4 | "description": "My slides.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "parcel index.html", 8 | "dist": "parcel build index.html -d docs --public-url https://juanuys.com/slides/", 9 | "build": "parcel build index.js", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/juanuys/slides.git" 15 | }, 16 | "keywords": [ 17 | "slides" 18 | ], 19 | "author": "Juan Uys", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/juanuys/slides/issues" 23 | }, 24 | "homepage": "https://github.com/juanuys/slides#readme", 25 | "devDependencies": { 26 | "parcel-bundler": "^1.12.4", 27 | "sass": "^1.26.11", 28 | "typescript": "^4.0.3" 29 | }, 30 | "dependencies": { 31 | "highlight.js": "^10.2.1", 32 | "reveal.js": "^4.0.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /scss/reset.scss: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v4.0 | 20180602 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | main, menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, main, menu, nav, section { 29 | display: block; 30 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Juan Uys 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scss/theme/template/exposer.scss: -------------------------------------------------------------------------------- 1 | // Exposes theme's variables for easy re-use in CSS for plugin authors 2 | 3 | :root { 4 | --background-color: #{$backgroundColor}; 5 | --main-font: #{$mainFont}; 6 | --main-font-size: #{$mainFontSize}; 7 | --main-color: #{$mainColor}; 8 | --block-margin: #{$blockMargin}; 9 | --heading-margin: #{$headingMargin}; 10 | --heading-font: #{$headingFont}; 11 | --heading-color: #{$headingColor}; 12 | --heading-line-height: #{$headingLineHeight}; 13 | --heading-letter-spacing: #{$headingLetterSpacing}; 14 | --heading-text-transform: #{$headingTextTransform}; 15 | --heading-text-shadow: #{$headingTextShadow}; 16 | --heading-font-weight: #{$headingFontWeight}; 17 | --heading1-text-shadow: #{$heading1TextShadow}; 18 | --heading1-size: #{$heading1Size}; 19 | --heading2-size: #{$heading2Size}; 20 | --heading3-size: #{$heading3Size}; 21 | --heading4-size: #{$heading4Size}; 22 | --code-font: #{$codeFont}; 23 | --link-color: #{$linkColor}; 24 | --link-color-hover: #{$linkColorHover}; 25 | --selection-background-color: #{$selectionBackgroundColor}; 26 | --selection-color: #{$selectionColor}; 27 | } 28 | -------------------------------------------------------------------------------- /docs/slides.f84e1103.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #3f3f3f; 13 | color: #dcdcdc; 14 | } 15 | 16 | .hljs-keyword, 17 | .hljs-selector-tag, 18 | .hljs-tag { 19 | color: #e3ceab; 20 | } 21 | 22 | .hljs-template-tag { 23 | color: #dcdcdc; 24 | } 25 | 26 | .hljs-number { 27 | color: #8cd0d3; 28 | } 29 | 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-attribute { 33 | color: #efdcbc; 34 | } 35 | 36 | .hljs-literal { 37 | color: #efefaf; 38 | } 39 | 40 | .hljs-subst { 41 | color: #8f8f8f; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-name, 46 | .hljs-selector-id, 47 | .hljs-selector-class, 48 | .hljs-section, 49 | .hljs-type { 50 | color: #efef8f; 51 | } 52 | 53 | .hljs-symbol, 54 | .hljs-bullet, 55 | .hljs-link { 56 | color: #dca3a3; 57 | } 58 | 59 | .hljs-deletion, 60 | .hljs-string, 61 | .hljs-built_in, 62 | .hljs-builtin-name { 63 | color: #cc9393; 64 | } 65 | 66 | .hljs-addition, 67 | .hljs-comment, 68 | .hljs-quote, 69 | .hljs-meta { 70 | color: #7f9f7f; 71 | } 72 | 73 | 74 | .hljs-emphasis { 75 | font-style: italic; 76 | } 77 | 78 | .hljs-strong { 79 | font-weight: bold; 80 | } 81 | -------------------------------------------------------------------------------- /scss/theme/source/league.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * League theme for reveal.js. 3 | * 4 | * This was the default theme pre-3.0.0. 5 | * 6 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se 7 | */ 8 | 9 | 10 | // Default mixins and settings ----------------- 11 | @import "../template/mixins"; 12 | @import "../template/settings"; 13 | // --------------------------------------------- 14 | 15 | 16 | 17 | // Include theme-specific fonts 18 | @import url(./fonts/league-gothic/league-gothic.css); 19 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); 20 | 21 | // Override theme settings (see ../template/settings.scss) 22 | $headingTextShadow: 0px 0px 6px rgba(0,0,0,0.2); 23 | $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); 24 | 25 | // Background generator 26 | @mixin bodyBackground() { 27 | @include radial-gradient( rgba(28,30,32,1), rgba(85,90,95,1) ); 28 | } 29 | 30 | // Change text colors against light slide backgrounds 31 | @include light-bg-text-color(#222); 32 | 33 | 34 | // Theme template ------------------------------ 35 | @import "../template/theme"; 36 | // --------------------------------------------- 37 | -------------------------------------------------------------------------------- /scss/theme/source/white.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * White theme for reveal.js. This is the opposite of the 'black' theme. 3 | * 4 | * By Hakim El Hattab, http://hakim.se 5 | */ 6 | 7 | 8 | // Default mixins and settings ----------------- 9 | @import "../template/mixins"; 10 | @import "../template/settings"; 11 | // --------------------------------------------- 12 | 13 | 14 | // Include theme-specific fonts 15 | @import url(./fonts/source-sans-pro/source-sans-pro.css); 16 | 17 | 18 | // Override theme settings (see ../template/settings.scss) 19 | $backgroundColor: #fff; 20 | 21 | $mainColor: #222; 22 | $headingColor: #222; 23 | 24 | $mainFontSize: 42px; 25 | $mainFont: 'Source Sans Pro', Helvetica, sans-serif; 26 | $headingFont: 'Source Sans Pro', Helvetica, sans-serif; 27 | $headingTextShadow: none; 28 | $headingLetterSpacing: normal; 29 | $headingTextTransform: uppercase; 30 | $headingFontWeight: 600; 31 | $linkColor: #2a76dd; 32 | $linkColorHover: lighten( $linkColor, 15% ); 33 | $selectionBackgroundColor: lighten( $linkColor, 25% ); 34 | 35 | $heading1Size: 2.5em; 36 | $heading2Size: 1.6em; 37 | $heading3Size: 1.3em; 38 | $heading4Size: 1.0em; 39 | 40 | // Change text colors against dark slide backgrounds 41 | @include dark-bg-text-color(#fff); 42 | 43 | 44 | // Theme template ------------------------------ 45 | @import "../template/theme"; 46 | // --------------------------------------------- 47 | -------------------------------------------------------------------------------- /meta/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 17 | 19 | 21 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /scss/theme/source/black.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Black theme for reveal.js. This is the opposite of the 'white' theme. 3 | * 4 | * By Hakim El Hattab, http://hakim.se 5 | */ 6 | 7 | 8 | // Default mixins and settings ----------------- 9 | @import "../template/mixins"; 10 | @import "../template/settings"; 11 | // --------------------------------------------- 12 | 13 | 14 | // Include theme-specific fonts 15 | @import url(./fonts/source-sans-pro/source-sans-pro.css); 16 | 17 | 18 | // Override theme settings (see ../template/settings.scss) 19 | $backgroundColor: #191919; 20 | 21 | $mainColor: #fff; 22 | $headingColor: #fff; 23 | 24 | $mainFontSize: 42px; 25 | $mainFont: 'Source Sans Pro', Helvetica, sans-serif; 26 | $headingFont: 'Source Sans Pro', Helvetica, sans-serif; 27 | $headingTextShadow: none; 28 | $headingLetterSpacing: normal; 29 | $headingTextTransform: uppercase; 30 | $headingFontWeight: 600; 31 | $linkColor: #42affa; 32 | $linkColorHover: lighten( $linkColor, 15% ); 33 | $selectionBackgroundColor: lighten( $linkColor, 25% ); 34 | 35 | $heading1Size: 2.5em; 36 | $heading2Size: 1.6em; 37 | $heading3Size: 1.3em; 38 | $heading4Size: 1.0em; 39 | 40 | // Change text colors against light slide backgrounds 41 | @include light-bg-text-color(#222); 42 | 43 | 44 | // Theme template ------------------------------ 45 | @import "../template/theme"; 46 | // --------------------------------------------- 47 | -------------------------------------------------------------------------------- /docs/safari-pinned-tab.ead9fee4.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 17 | 19 | 21 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /scss/theme/source/simple.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * A simple theme for reveal.js presentations, similar 3 | * to the default theme. The accent color is darkblue. 4 | * 5 | * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed. 6 | * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se 7 | */ 8 | 9 | 10 | // Default mixins and settings ----------------- 11 | @import "../template/mixins"; 12 | @import "../template/settings"; 13 | // --------------------------------------------- 14 | 15 | 16 | 17 | // Include theme-specific fonts 18 | @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700); 19 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); 20 | 21 | 22 | // Override theme settings (see ../template/settings.scss) 23 | $mainFont: 'Lato', sans-serif; 24 | $mainColor: #000; 25 | $headingFont: 'News Cycle', Impact, sans-serif; 26 | $headingColor: #000; 27 | $headingTextShadow: none; 28 | $headingTextTransform: none; 29 | $backgroundColor: #fff; 30 | $linkColor: #00008B; 31 | $linkColorHover: lighten( $linkColor, 20% ); 32 | $selectionBackgroundColor: rgba(0, 0, 0, 0.99); 33 | 34 | // Change text colors against dark slide backgrounds 35 | @include dark-bg-text-color(#fff); 36 | 37 | 38 | // Theme template ------------------------------ 39 | @import "../template/theme"; 40 | // --------------------------------------------- -------------------------------------------------------------------------------- /scss/theme/source/sky.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Sky theme for reveal.js. 3 | * 4 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se 5 | */ 6 | 7 | 8 | // Default mixins and settings ----------------- 9 | @import "../template/mixins"; 10 | @import "../template/settings"; 11 | // --------------------------------------------- 12 | 13 | 14 | 15 | // Include theme-specific fonts 16 | @import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic); 17 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); 18 | 19 | 20 | // Override theme settings (see ../template/settings.scss) 21 | $mainFont: 'Open Sans', sans-serif; 22 | $mainColor: #333; 23 | $headingFont: 'Quicksand', sans-serif; 24 | $headingColor: #333; 25 | $headingLetterSpacing: -0.08em; 26 | $headingTextShadow: none; 27 | $backgroundColor: #f7fbfc; 28 | $linkColor: #3b759e; 29 | $linkColorHover: lighten( $linkColor, 20% ); 30 | $selectionBackgroundColor: #134674; 31 | 32 | // Fix links so they are not cut off 33 | .reveal a { 34 | line-height: 1.3em; 35 | } 36 | 37 | // Background generator 38 | @mixin bodyBackground() { 39 | @include radial-gradient( #add9e4, #f7fbfc ); 40 | } 41 | 42 | // Change text colors against dark slide backgrounds 43 | @include dark-bg-text-color(#fff); 44 | 45 | 46 | 47 | // Theme template ------------------------------ 48 | @import "../template/theme"; 49 | // --------------------------------------------- 50 | -------------------------------------------------------------------------------- /scss/theme/source/beige.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Beige theme for reveal.js. 3 | * 4 | * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se 5 | */ 6 | 7 | 8 | // Default mixins and settings ----------------- 9 | @import "../template/mixins"; 10 | @import "../template/settings"; 11 | // --------------------------------------------- 12 | 13 | 14 | 15 | // Include theme-specific fonts 16 | @import url(./fonts/league-gothic/league-gothic.css); 17 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic); 18 | 19 | 20 | // Override theme settings (see ../template/settings.scss) 21 | $mainColor: #333; 22 | $headingColor: #333; 23 | $headingTextShadow: none; 24 | $backgroundColor: #f7f3de; 25 | $linkColor: #8b743d; 26 | $linkColorHover: lighten( $linkColor, 20% ); 27 | $selectionBackgroundColor: rgba(79, 64, 28, 0.99); 28 | $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); 29 | 30 | // Background generator 31 | @mixin bodyBackground() { 32 | @include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) ); 33 | } 34 | 35 | // Change text colors against dark slide backgrounds 36 | @include dark-bg-text-color(#fff); 37 | 38 | 39 | // Theme template ------------------------------ 40 | @import "../template/theme"; 41 | // --------------------------------------------- 42 | -------------------------------------------------------------------------------- /js/math/math.esm.js: -------------------------------------------------------------------------------- 1 | function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(n){for(var r=1;r * { 31 | grid-area: 1/1; 32 | margin: auto; 33 | } 34 | 35 | // Horizontal and vertical stacks 36 | .reveal .r-vstack, 37 | .reveal .r-hstack { 38 | display: flex; 39 | 40 | img, video { 41 | min-width: 0; 42 | min-height: 0; 43 | object-fit: contain; 44 | } 45 | } 46 | 47 | .reveal .r-vstack { 48 | flex-direction: column; 49 | align-items: center; 50 | justify-content: center; 51 | } 52 | 53 | .reveal .r-hstack { 54 | flex-direction: row; 55 | align-items: center; 56 | justify-content: center; 57 | } 58 | 59 | // Naming based on tailwindcss 60 | .reveal .items-stretch { align-items: stretch; } 61 | .reveal .items-start { align-items: flex-start; } 62 | .reveal .items-center { align-items: center; } 63 | .reveal .items-end { align-items: flex-end; } 64 | 65 | .reveal .justify-between { justify-content: space-between; } 66 | .reveal .justify-around { justify-content: space-around; } 67 | .reveal .justify-start { justify-content: flex-start; } 68 | .reveal .justify-center { justify-content: center; } 69 | .reveal .justify-end { justify-content: flex-end; } 70 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | Juan Uys' slides
2 | -------------------------------------------------------------------------------- /js/math/math.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).RevealMath=t()}(this,(function(){"use strict";function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function n(n){for(var r=1;r 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Juan Uys' slides 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 48 |
49 | 50 | 51 | -------------------------------------------------------------------------------- /scss/theme/template/mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin vertical-gradient( $top, $bottom ) { 2 | background: $top; 3 | background: -moz-linear-gradient( top, $top 0%, $bottom 100% ); 4 | background: -webkit-gradient( linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom) ); 5 | background: -webkit-linear-gradient( top, $top 0%, $bottom 100% ); 6 | background: -o-linear-gradient( top, $top 0%, $bottom 100% ); 7 | background: -ms-linear-gradient( top, $top 0%, $bottom 100% ); 8 | background: linear-gradient( top, $top 0%, $bottom 100% ); 9 | } 10 | 11 | @mixin horizontal-gradient( $top, $bottom ) { 12 | background: $top; 13 | background: -moz-linear-gradient( left, $top 0%, $bottom 100% ); 14 | background: -webkit-gradient( linear, left top, right top, color-stop(0%,$top), color-stop(100%,$bottom) ); 15 | background: -webkit-linear-gradient( left, $top 0%, $bottom 100% ); 16 | background: -o-linear-gradient( left, $top 0%, $bottom 100% ); 17 | background: -ms-linear-gradient( left, $top 0%, $bottom 100% ); 18 | background: linear-gradient( left, $top 0%, $bottom 100% ); 19 | } 20 | 21 | @mixin radial-gradient( $outer, $inner, $type: circle ) { 22 | background: $outer; 23 | background: -moz-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); 24 | background: -webkit-gradient( radial, center center, 0px, center center, 100%, color-stop(0%,$inner), color-stop(100%,$outer) ); 25 | background: -webkit-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); 26 | background: -o-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); 27 | background: -ms-radial-gradient( center, $type cover, $inner 0%, $outer 100% ); 28 | background: radial-gradient( center, $type cover, $inner 0%, $outer 100% ); 29 | } 30 | 31 | @mixin light-bg-text-color( $color ) { 32 | section.has-light-background { 33 | &, h1, h2, h3, h4, h5, h6 { 34 | color: $color; 35 | } 36 | } 37 | } 38 | 39 | @mixin dark-bg-text-color( $color ) { 40 | section.has-dark-background { 41 | &, h1, h2, h3, h4, h5, h6 { 42 | color: $color; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /scss/theme/source/blood.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Blood theme for reveal.js 3 | * Author: Walther http://github.com/Walther 4 | * 5 | * Designed to be used with highlight.js theme 6 | * "monokai_sublime.css" available from 7 | * https://github.com/isagalaev/highlight.js/ 8 | * 9 | * For other themes, change $codeBackground accordingly. 10 | * 11 | */ 12 | 13 | // Default mixins and settings ----------------- 14 | @import "../template/mixins"; 15 | @import "../template/settings"; 16 | // --------------------------------------------- 17 | 18 | // Include theme-specific fonts 19 | 20 | @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,700,300italic,700italic); 21 | 22 | // Colors used in the theme 23 | $blood: #a23; 24 | $coal: #222; 25 | $codeBackground: #23241f; 26 | 27 | $backgroundColor: $coal; 28 | 29 | // Main text 30 | $mainFont: Ubuntu, 'sans-serif'; 31 | $mainColor: #eee; 32 | 33 | // Headings 34 | $headingFont: Ubuntu, 'sans-serif'; 35 | $headingTextShadow: 2px 2px 2px $coal; 36 | 37 | // h1 shadow, borrowed humbly from 38 | // (c) Default theme by Hakim El Hattab 39 | $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); 40 | 41 | // Links 42 | $linkColor: $blood; 43 | $linkColorHover: lighten( $linkColor, 20% ); 44 | 45 | // Text selection 46 | $selectionBackgroundColor: $blood; 47 | $selectionColor: #fff; 48 | 49 | // Change text colors against dark slide backgrounds 50 | @include light-bg-text-color(#222); 51 | 52 | 53 | // Theme template ------------------------------ 54 | @import "../template/theme"; 55 | // --------------------------------------------- 56 | 57 | // some overrides after theme template import 58 | 59 | .reveal p { 60 | font-weight: 300; 61 | text-shadow: 1px 1px $coal; 62 | } 63 | 64 | section.has-light-background { 65 | p, h1, h2, h3, h4 { 66 | text-shadow: none; 67 | } 68 | } 69 | 70 | .reveal h1, 71 | .reveal h2, 72 | .reveal h3, 73 | .reveal h4, 74 | .reveal h5, 75 | .reveal h6 { 76 | font-weight: 700; 77 | } 78 | 79 | .reveal p code { 80 | background-color: $codeBackground; 81 | display: inline-block; 82 | border-radius: 7px; 83 | } 84 | 85 | .reveal small code { 86 | vertical-align: baseline; 87 | } -------------------------------------------------------------------------------- /js/math/plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A plugin which enables rendering of math equations inside 3 | * of reveal.js slides. Essentially a thin wrapper for MathJax. 4 | * 5 | * @author Hakim El Hattab 6 | */ 7 | const Plugin = () => { 8 | 9 | // The reveal.js instance this plugin is attached to 10 | let deck; 11 | 12 | let defaultOptions = { 13 | messageStyle: 'none', 14 | tex2jax: { 15 | inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ], 16 | skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ] 17 | }, 18 | skipStartupTypeset: true 19 | }; 20 | 21 | function loadScript( url, callback ) { 22 | 23 | let head = document.querySelector( 'head' ); 24 | let script = document.createElement( 'script' ); 25 | script.type = 'text/javascript'; 26 | script.src = url; 27 | 28 | // Wrapper for callback to make sure it only fires once 29 | let finish = () => { 30 | if( typeof callback === 'function' ) { 31 | callback.call(); 32 | callback = null; 33 | } 34 | } 35 | 36 | script.onload = finish; 37 | 38 | // IE 39 | script.onreadystatechange = () => { 40 | if ( this.readyState === 'loaded' ) { 41 | finish(); 42 | } 43 | } 44 | 45 | // Normal browsers 46 | head.appendChild( script ); 47 | 48 | } 49 | 50 | return { 51 | id: 'math', 52 | 53 | init: function( reveal ) { 54 | 55 | deck = reveal; 56 | 57 | let revealOptions = deck.getConfig().math || {}; 58 | 59 | let options = { ...defaultOptions, ...revealOptions }; 60 | let mathjax = options.mathjax || 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js'; 61 | let config = options.config || 'TeX-AMS_HTML-full'; 62 | let url = mathjax + '?config=' + config; 63 | 64 | options.tex2jax = { ...defaultOptions.tex2jax, ...revealOptions.tex2jax }; 65 | 66 | options.mathjax = options.config = null; 67 | 68 | loadScript( url, function() { 69 | 70 | MathJax.Hub.Config( options ); 71 | 72 | // Typeset followed by an immediate reveal.js layout since 73 | // the typesetting process could affect slide height 74 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, deck.getRevealElement() ] ); 75 | MathJax.Hub.Queue( deck.layout ); 76 | 77 | // Reprocess equations in slides when they turn visible 78 | deck.on( 'slidechanged', function( event ) { 79 | 80 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] ); 81 | 82 | } ); 83 | 84 | } ); 85 | 86 | } 87 | } 88 | 89 | }; 90 | 91 | export default Plugin; 92 | -------------------------------------------------------------------------------- /js/zoom/zoom.esm.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * reveal.js Zoom plugin 3 | */ 4 | var e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(o){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;o[i]&&!e.isOverview()&&(o.preventDefault(),t.to({x:o.clientX,y:o.clientY,scale:d,pan:!1}))}))}},t=function(){var e=1,o=0,n=0,i=-1,d=-1,s="WebkitTransform"in document.body.style||"MozTransform"in document.body.style||"msTransform"in document.body.style||"OTransform"in document.body.style||"transform"in document.body.style;function r(t,o){var n=y();if(t.width=t.width||1,t.height=t.height||1,t.x-=(window.innerWidth-t.width*o)/2,t.y-=(window.innerHeight-t.height*o)/2,s)if(1===o)document.body.style.transform="",document.body.style.OTransform="",document.body.style.msTransform="",document.body.style.MozTransform="",document.body.style.WebkitTransform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-t.x+"px,"+-t.y+"px) scale("+o+")";document.body.style.transformOrigin=i,document.body.style.OTransformOrigin=i,document.body.style.msTransformOrigin=i,document.body.style.MozTransformOrigin=i,document.body.style.WebkitTransformOrigin=i,document.body.style.transform=d,document.body.style.OTransform=d,document.body.style.msTransform=d,document.body.style.MozTransform=d,document.body.style.WebkitTransform=d}else 1===o?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+t.x)/o+"px",document.body.style.top=-(n.y+t.y)/o+"px",document.body.style.width=100*o+"%",document.body.style.height=100*o+"%",document.body.style.zoom=o);e=o,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function m(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=y();nwindow.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),owindow.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function y(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return s&&(document.body.style.transition="transform 0.8s ease",document.body.style.OTransition="-o-transform 0.8s ease",document.body.style.msTransition="-ms-transform 0.8s ease",document.body.style.MozTransition="-moz-transform 0.8s ease",document.body.style.WebkitTransition="-webkit-transform 0.8s ease"),document.addEventListener("keyup",(function(o){1!==e&&27===o.keyCode&&t.out()})),document.addEventListener("mousemove",(function(t){1!==e&&(o=t.clientX,n=t.clientY)})),{to:function(o){if(1!==e)t.out();else{if(o.x=o.x||0,o.y=o.y||0,o.element){var n=o.element.getBoundingClientRect();o.x=n.left-20,o.y=n.top-20,o.width=n.width+40,o.height=n.height+40}void 0!==o.width&&void 0!==o.height&&(o.scale=Math.max(Math.min(window.innerWidth/o.width,window.innerHeight/o.height),1)),o.scale>1&&(o.x*=o.scale,o.y*=o.scale,r(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(m,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),r({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();export default function(){return e} 5 | -------------------------------------------------------------------------------- /js/zoom/zoom.js: -------------------------------------------------------------------------------- 1 | !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?module.exports=o():"function"==typeof define&&define.amd?define(o):(e="undefined"!=typeof globalThis?globalThis:e||self).RevealZoom=o()}(this,(function(){"use strict"; 2 | /*! 3 | * reveal.js Zoom plugin 4 | */var e={id:"zoom",init:function(e){e.getRevealElement().addEventListener("mousedown",(function(t){var n=/Linux/.test(window.navigator.platform)?"ctrl":"alt",i=(e.getConfig().zoomKey?e.getConfig().zoomKey:n)+"Key",d=e.getConfig().zoomLevel?e.getConfig().zoomLevel:2;t[i]&&!e.isOverview()&&(t.preventDefault(),o.to({x:t.clientX,y:t.clientY,scale:d,pan:!1}))}))}},o=function(){var e=1,t=0,n=0,i=-1,d=-1,s="WebkitTransform"in document.body.style||"MozTransform"in document.body.style||"msTransform"in document.body.style||"OTransform"in document.body.style||"transform"in document.body.style;function r(o,t){var n=l();if(o.width=o.width||1,o.height=o.height||1,o.x-=(window.innerWidth-o.width*t)/2,o.y-=(window.innerHeight-o.height*t)/2,s)if(1===t)document.body.style.transform="",document.body.style.OTransform="",document.body.style.msTransform="",document.body.style.MozTransform="",document.body.style.WebkitTransform="";else{var i=n.x+"px "+n.y+"px",d="translate("+-o.x+"px,"+-o.y+"px) scale("+t+")";document.body.style.transformOrigin=i,document.body.style.OTransformOrigin=i,document.body.style.msTransformOrigin=i,document.body.style.MozTransformOrigin=i,document.body.style.WebkitTransformOrigin=i,document.body.style.transform=d,document.body.style.OTransform=d,document.body.style.msTransform=d,document.body.style.MozTransform=d,document.body.style.WebkitTransform=d}else 1===t?(document.body.style.position="",document.body.style.left="",document.body.style.top="",document.body.style.width="",document.body.style.height="",document.body.style.zoom=""):(document.body.style.position="relative",document.body.style.left=-(n.x+o.x)/t+"px",document.body.style.top=-(n.y+o.y)/t+"px",document.body.style.width=100*t+"%",document.body.style.height=100*t+"%",document.body.style.zoom=t);e=t,document.documentElement.classList&&(1!==e?document.documentElement.classList.add("zoomed"):document.documentElement.classList.remove("zoomed"))}function m(){var o=.12*window.innerWidth,i=.12*window.innerHeight,d=l();nwindow.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),twindow.innerWidth-o&&window.scroll(d.x+(1-(window.innerWidth-t)/o)*(14/e),d.y)}function l(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return s&&(document.body.style.transition="transform 0.8s ease",document.body.style.OTransition="-o-transform 0.8s ease",document.body.style.msTransition="-ms-transform 0.8s ease",document.body.style.MozTransition="-moz-transform 0.8s ease",document.body.style.WebkitTransition="-webkit-transform 0.8s ease"),document.addEventListener("keyup",(function(t){1!==e&&27===t.keyCode&&o.out()})),document.addEventListener("mousemove",(function(o){1!==e&&(t=o.clientX,n=o.clientY)})),{to:function(t){if(1!==e)o.out();else{if(t.x=t.x||0,t.y=t.y||0,t.element){var n=t.element.getBoundingClientRect();t.x=n.left-20,t.y=n.top-20,t.width=n.width+40,t.height=n.height+40}void 0!==t.width&&void 0!==t.height&&(t.scale=Math.max(Math.min(window.innerWidth/t.width,window.innerHeight/t.height),1)),t.scale>1&&(t.x*=t.scale,t.y*=t.scale,r(t,t.scale),!1!==t.pan&&(i=setTimeout((function(){d=setInterval(m,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),r({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();return function(){return e}})); 5 | -------------------------------------------------------------------------------- /scss/print/pdf.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * This stylesheet is used to print reveal.js 3 | * presentations to PDF. 4 | * 5 | * https://revealjs.com/pdf-export/ 6 | */ 7 | 8 | html.print-pdf { 9 | * { 10 | -webkit-print-color-adjust: exact; 11 | } 12 | 13 | & { 14 | width: 100%; 15 | height: 100%; 16 | overflow: visible; 17 | } 18 | 19 | body { 20 | margin: 0 auto !important; 21 | border: 0; 22 | padding: 0; 23 | float: none !important; 24 | overflow: visible; 25 | } 26 | 27 | /* Remove any elements not needed in print. */ 28 | .nestedarrow, 29 | .reveal .controls, 30 | .reveal .progress, 31 | .reveal .playback, 32 | .reveal.overview, 33 | .state-background { 34 | display: none !important; 35 | } 36 | 37 | .reveal pre code { 38 | overflow: hidden !important; 39 | font-family: Courier, 'Courier New', monospace !important; 40 | } 41 | 42 | .reveal { 43 | width: auto !important; 44 | height: auto !important; 45 | overflow: hidden !important; 46 | } 47 | .reveal .slides { 48 | position: static; 49 | width: 100% !important; 50 | height: auto !important; 51 | zoom: 1 !important; 52 | pointer-events: initial; 53 | 54 | left: auto; 55 | top: auto; 56 | margin: 0 !important; 57 | padding: 0 !important; 58 | 59 | overflow: visible; 60 | display: block; 61 | 62 | perspective: none; 63 | perspective-origin: 50% 50%; 64 | } 65 | 66 | .reveal .slides .pdf-page { 67 | position: relative; 68 | overflow: hidden; 69 | z-index: 1; 70 | 71 | page-break-after: always; 72 | } 73 | 74 | .reveal .slides section { 75 | visibility: visible !important; 76 | display: block !important; 77 | position: absolute !important; 78 | 79 | margin: 0 !important; 80 | padding: 0 !important; 81 | box-sizing: border-box !important; 82 | min-height: 1px; 83 | 84 | opacity: 1 !important; 85 | 86 | transform-style: flat !important; 87 | transform: none !important; 88 | } 89 | 90 | .reveal section.stack { 91 | position: relative !important; 92 | margin: 0 !important; 93 | padding: 0 !important; 94 | page-break-after: avoid !important; 95 | height: auto !important; 96 | min-height: auto !important; 97 | } 98 | 99 | .reveal img { 100 | box-shadow: none; 101 | } 102 | 103 | 104 | /* Slide backgrounds are placed inside of their slide when exporting to PDF */ 105 | .reveal .backgrounds { 106 | display: none; 107 | } 108 | .reveal .slide-background { 109 | display: block !important; 110 | position: absolute; 111 | top: 0; 112 | left: 0; 113 | width: 100%; 114 | height: 100%; 115 | z-index: auto !important; 116 | } 117 | 118 | /* Display slide speaker notes when 'showNotes' is enabled */ 119 | .reveal.show-notes { 120 | max-width: none; 121 | max-height: none; 122 | } 123 | .reveal .speaker-notes-pdf { 124 | display: block; 125 | width: 100%; 126 | height: auto; 127 | max-height: none; 128 | top: auto; 129 | right: auto; 130 | bottom: auto; 131 | left: auto; 132 | z-index: 100; 133 | } 134 | 135 | /* Layout option which makes notes appear on a separate page */ 136 | .reveal .speaker-notes-pdf[data-layout="separate-page"] { 137 | position: relative; 138 | color: inherit; 139 | background-color: transparent; 140 | padding: 20px; 141 | page-break-after: always; 142 | border: 0; 143 | } 144 | 145 | /* Display slide numbers when 'slideNumber' is enabled */ 146 | .reveal .slide-number-pdf { 147 | display: block; 148 | position: absolute; 149 | font-size: 14px; 150 | } 151 | 152 | /* This accessibility tool is not useful in PDF and breaks it visually */ 153 | .aria-status { 154 | display: none; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /scss/print/paper.scss: -------------------------------------------------------------------------------- 1 | /* Default Print Stylesheet Template 2 | by Rob Glazebrook of CSSnewbie.com 3 | Last Updated: June 4, 2008 4 | 5 | Feel free (nay, compelled) to edit, append, and 6 | manipulate this file as you see fit. */ 7 | 8 | @media print { 9 | html:not(.print-pdf) { 10 | 11 | background: #fff; 12 | width: auto; 13 | height: auto; 14 | overflow: visible; 15 | 16 | body { 17 | background: #fff; 18 | font-size: 20pt; 19 | width: auto; 20 | height: auto; 21 | border: 0; 22 | margin: 0 5%; 23 | padding: 0; 24 | overflow: visible; 25 | float: none !important; 26 | } 27 | 28 | .nestedarrow, 29 | .controls, 30 | .fork-reveal, 31 | .share-reveal, 32 | .state-background, 33 | .reveal .progress, 34 | .reveal .backgrounds, 35 | .reveal .slide-number { 36 | display: none !important; 37 | } 38 | 39 | body, p, td, li { 40 | font-size: 20pt!important; 41 | color: #000; 42 | } 43 | 44 | h1,h2,h3,h4,h5,h6 { 45 | color: #000!important; 46 | height: auto; 47 | line-height: normal; 48 | text-align: left; 49 | letter-spacing: normal; 50 | } 51 | 52 | /* Need to reduce the size of the fonts for printing */ 53 | h1 { font-size: 28pt !important; } 54 | h2 { font-size: 24pt !important; } 55 | h3 { font-size: 22pt !important; } 56 | h4 { font-size: 22pt !important; font-variant: small-caps; } 57 | h5 { font-size: 21pt !important; } 58 | h6 { font-size: 20pt !important; font-style: italic; } 59 | 60 | a:link, 61 | a:visited { 62 | color: #000 !important; 63 | font-weight: bold; 64 | text-decoration: underline; 65 | } 66 | 67 | ul, ol, div, p { 68 | visibility: visible; 69 | position: static; 70 | width: auto; 71 | height: auto; 72 | display: block; 73 | overflow: visible; 74 | margin: 0; 75 | text-align: left !important; 76 | } 77 | .reveal pre, 78 | .reveal table { 79 | margin-left: 0; 80 | margin-right: 0; 81 | } 82 | .reveal pre code { 83 | padding: 20px; 84 | } 85 | .reveal blockquote { 86 | margin: 20px 0; 87 | } 88 | .reveal .slides { 89 | position: static !important; 90 | width: auto !important; 91 | height: auto !important; 92 | 93 | left: 0 !important; 94 | top: 0 !important; 95 | margin-left: 0 !important; 96 | margin-top: 0 !important; 97 | padding: 0 !important; 98 | zoom: 1 !important; 99 | transform: none !important; 100 | 101 | overflow: visible !important; 102 | display: block !important; 103 | 104 | text-align: left !important; 105 | perspective: none; 106 | 107 | perspective-origin: 50% 50%; 108 | } 109 | .reveal .slides section { 110 | visibility: visible !important; 111 | position: static !important; 112 | width: auto !important; 113 | height: auto !important; 114 | display: block !important; 115 | overflow: visible !important; 116 | 117 | left: 0 !important; 118 | top: 0 !important; 119 | margin-left: 0 !important; 120 | margin-top: 0 !important; 121 | padding: 60px 20px !important; 122 | z-index: auto !important; 123 | 124 | opacity: 1 !important; 125 | 126 | page-break-after: always !important; 127 | 128 | transform-style: flat !important; 129 | transform: none !important; 130 | transition: none !important; 131 | } 132 | .reveal .slides section.stack { 133 | padding: 0 !important; 134 | } 135 | .reveal section:last-of-type { 136 | page-break-after: avoid !important; 137 | } 138 | .reveal section .fragment { 139 | opacity: 1 !important; 140 | visibility: visible !important; 141 | 142 | transform: none !important; 143 | } 144 | .reveal section img { 145 | display: block; 146 | margin: 15px 0px; 147 | background: rgba(255,255,255,1); 148 | border: 1px solid #666; 149 | box-shadow: none; 150 | } 151 | 152 | .reveal section small { 153 | font-size: 0.8em; 154 | } 155 | 156 | .reveal .hljs { 157 | max-height: 100%; 158 | white-space: pre-wrap; 159 | word-wrap: break-word; 160 | word-break: break-word; 161 | font-size: 15pt; 162 | } 163 | 164 | .reveal .hljs .hljs-ln-numbers { 165 | white-space: nowrap; 166 | } 167 | 168 | .reveal .hljs td { 169 | font-size: inherit !important; 170 | color: inherit !important; 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /scss/fonts/source-sans-pro/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License 2 | 3 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 4 | 5 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 6 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 7 | 8 | —————————————————————————————- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | —————————————————————————————- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. 14 | 15 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. 16 | 17 | DEFINITIONS 18 | “Font Software” refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. 19 | 20 | “Reserved Font Name” refers to any names specified as such after the copyright statement(s). 21 | 22 | “Original Version” refers to the collection of Font Software components as distributed by the Copyright Holder(s). 23 | 24 | “Modified Version” refers to any derivative made by adding to, deleting, or substituting—in part or in whole—any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. 25 | 26 | “Author” refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. 27 | 28 | PERMISSION & CONDITIONS 29 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 30 | 31 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 32 | 33 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 34 | 35 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 36 | 37 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 38 | 39 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 40 | 41 | TERMINATION 42 | This license becomes null and void if any of the above conditions are not met. 43 | 44 | DISCLAIMER 45 | THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /scss/theme/source/fonts/source-sans-pro/LICENSE: -------------------------------------------------------------------------------- 1 | SIL Open Font License 2 | 3 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 4 | 5 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 6 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 7 | 8 | —————————————————————————————- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | —————————————————————————————- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. 14 | 15 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. 16 | 17 | DEFINITIONS 18 | “Font Software” refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. 19 | 20 | “Reserved Font Name” refers to any names specified as such after the copyright statement(s). 21 | 22 | “Original Version” refers to the collection of Font Software components as distributed by the Copyright Holder(s). 23 | 24 | “Modified Version” refers to any derivative made by adding to, deleting, or substituting—in part or in whole—any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. 25 | 26 | “Author” refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. 27 | 28 | PERMISSION & CONDITIONS 29 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 30 | 31 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 32 | 33 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 34 | 35 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 36 | 37 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 38 | 39 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 40 | 41 | TERMINATION 42 | This license becomes null and void if any of the above conditions are not met. 43 | 44 | DISCLAIMER 45 | THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /js/notes/plugin.js: -------------------------------------------------------------------------------- 1 | import speakerViewHTML from './speaker-view.html'; 2 | 3 | import marked from 'marked'; 4 | 5 | /** 6 | * Handles opening of and synchronization with the reveal.js 7 | * notes window. 8 | * 9 | * Handshake process: 10 | * 1. This window posts 'connect' to notes window 11 | * - Includes URL of presentation to show 12 | * 2. Notes window responds with 'connected' when it is available 13 | * 3. This window proceeds to send the current presentation state 14 | * to the notes window 15 | */ 16 | const Plugin = () => { 17 | 18 | let popup = null; 19 | 20 | let deck; 21 | 22 | function openNotes() { 23 | 24 | if (popup && !popup.closed) { 25 | popup.focus(); 26 | return; 27 | } 28 | 29 | popup = window.open( 'about:blank', 'reveal.js - Notes', 'width=1100,height=700' ); 30 | popup.marked = marked; 31 | popup.document.write( speakerViewHTML ); 32 | 33 | if( !popup ) { 34 | alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' ); 35 | return; 36 | } 37 | 38 | /** 39 | * Connect to the notes window through a postmessage handshake. 40 | * Using postmessage enables us to work in situations where the 41 | * origins differ, such as a presentation being opened from the 42 | * file system. 43 | */ 44 | function connect() { 45 | // Keep trying to connect until we get a 'connected' message back 46 | let connectInterval = setInterval( function() { 47 | popup.postMessage( JSON.stringify( { 48 | namespace: 'reveal-notes', 49 | type: 'connect', 50 | url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search, 51 | state: deck.getState() 52 | } ), '*' ); 53 | }, 500 ); 54 | 55 | window.addEventListener( 'message', function( event ) { 56 | let data = JSON.parse( event.data ); 57 | if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) { 58 | clearInterval( connectInterval ); 59 | onConnected(); 60 | } 61 | if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) { 62 | callRevealApi( data.methodName, data.arguments, data.callId ); 63 | } 64 | } ); 65 | } 66 | 67 | /** 68 | * Calls the specified Reveal.js method with the provided argument 69 | * and then pushes the result to the notes frame. 70 | */ 71 | function callRevealApi( methodName, methodArguments, callId ) { 72 | 73 | let result = deck[methodName].apply( deck, methodArguments ); 74 | popup.postMessage( JSON.stringify( { 75 | namespace: 'reveal-notes', 76 | type: 'return', 77 | result: result, 78 | callId: callId 79 | } ), '*' ); 80 | 81 | } 82 | 83 | /** 84 | * Posts the current slide data to the notes window 85 | */ 86 | function post( event ) { 87 | 88 | let slideElement = deck.getCurrentSlide(), 89 | notesElement = slideElement.querySelector( 'aside.notes' ), 90 | fragmentElement = slideElement.querySelector( '.current-fragment' ); 91 | 92 | let messageData = { 93 | namespace: 'reveal-notes', 94 | type: 'state', 95 | notes: '', 96 | markdown: false, 97 | whitespace: 'normal', 98 | state: deck.getState() 99 | }; 100 | 101 | // Look for notes defined in a slide attribute 102 | if( slideElement.hasAttribute( 'data-notes' ) ) { 103 | messageData.notes = slideElement.getAttribute( 'data-notes' ); 104 | messageData.whitespace = 'pre-wrap'; 105 | } 106 | 107 | // Look for notes defined in a fragment 108 | if( fragmentElement ) { 109 | let fragmentNotes = fragmentElement.querySelector( 'aside.notes' ); 110 | if( fragmentNotes ) { 111 | notesElement = fragmentNotes; 112 | } 113 | else if( fragmentElement.hasAttribute( 'data-notes' ) ) { 114 | messageData.notes = fragmentElement.getAttribute( 'data-notes' ); 115 | messageData.whitespace = 'pre-wrap'; 116 | 117 | // In case there are slide notes 118 | notesElement = null; 119 | } 120 | } 121 | 122 | // Look for notes defined in an aside element 123 | if( notesElement ) { 124 | messageData.notes = notesElement.innerHTML; 125 | messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; 126 | } 127 | 128 | popup.postMessage( JSON.stringify( messageData ), '*' ); 129 | 130 | } 131 | 132 | /** 133 | * Called once we have established a connection to the notes 134 | * window. 135 | */ 136 | function onConnected() { 137 | 138 | // Monitor events that trigger a change in state 139 | deck.on( 'slidechanged', post ); 140 | deck.on( 'fragmentshown', post ); 141 | deck.on( 'fragmenthidden', post ); 142 | deck.on( 'overviewhidden', post ); 143 | deck.on( 'overviewshown', post ); 144 | deck.on( 'paused', post ); 145 | deck.on( 'resumed', post ); 146 | 147 | // Post the initial state 148 | post(); 149 | 150 | } 151 | 152 | connect(); 153 | 154 | } 155 | 156 | return { 157 | id: 'notes', 158 | 159 | init: function( reveal ) { 160 | 161 | deck = reveal; 162 | 163 | if( !/receiver/i.test( window.location.search ) ) { 164 | 165 | // If the there's a 'notes' query set, open directly 166 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { 167 | openNotes(); 168 | } 169 | 170 | // Open the notes when the 's' key is hit 171 | deck.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() { 172 | openNotes(); 173 | } ); 174 | 175 | } 176 | 177 | }, 178 | 179 | open: openNotes 180 | }; 181 | 182 | }; 183 | 184 | export default Plugin; 185 | -------------------------------------------------------------------------------- /docs/slides/disco-prelysium/index.html: -------------------------------------------------------------------------------- 1 | Juan Uys - Disco PRElysium

Disco Pre-lysium

If Disco Elysium was prototyped today.

Disco Elysium official artwork, Copyright ZA/UM

In this exercise, I'll simulate the planning stage of Disco Elysium using a variety of prototyping techniques:

  • wireframing
  • sketching
  • narrative prototyping

wireframing

Here we try a bunch of screen layouts, colour-coded as follows:

  • dialogue
  • inventory
  • world

wireframing

On the left, we split gameplay and conversation down the middle, but it feels like we're giving too much space to the conversation. We try to make it smaller, but is it too small?

wireframe 1
  • dialogue
  • inventory
  • world

wireframing

Let's try thirds. That looks nice. OK, how about inventory? On the left below gameplay, or on the right below the conversation?

wireframe 2
  • dialogue
  • inventory
  • world

wireframing

Definitely below conversation, so we can have a nice, large gameplay area. But let's not be all squares. How about a trapezoid? And a ...bit... more space for conversation. OK, that looks good.

wireframe 3
  • dialogue
  • inventory
  • world

wireframing

Right, that's a good layout. Let's see some rough concept art in it, shall we?

wireframe final choice

sketching

Dark and gritty, just like the protagonist.

Rough sketch of game world and some characters
Robert Kurvitz
Robert Kurvitz, lead game designer

OK, stop. I know this is based on my novel and all, but is there a way we can test the dialogue before we spend LOADS of time drawing stuff and coding something?

I mean, we already spent LOADS of time on the wireframes...

narrative prototyping

We've got just the tool.

Twine.

You mean this?

The wrong kind of Twine

Not THAT kind of Twine...

narrative prototyping

The right kind of Twine
twinery.org

This next section is Copyright © Alexei Pepers / @ampepers

Don't skip ahead. Click the red Continue button to follow the story...

FIN



(back to the blog)
2 | -------------------------------------------------------------------------------- /scss/theme/template/theme.scss: -------------------------------------------------------------------------------- 1 | // Base theme template for reveal.js 2 | 3 | /********************************************* 4 | * GLOBAL STYLES 5 | *********************************************/ 6 | 7 | @import "./exposer"; 8 | 9 | .reveal-viewport { 10 | @include bodyBackground(); 11 | background-color: $backgroundColor; 12 | } 13 | 14 | .reveal { 15 | font-family: $mainFont; 16 | font-size: $mainFontSize; 17 | font-weight: normal; 18 | color: $mainColor; 19 | } 20 | 21 | .reveal ::selection { 22 | color: $selectionColor; 23 | background: $selectionBackgroundColor; 24 | text-shadow: none; 25 | } 26 | 27 | .reveal ::-moz-selection { 28 | color: $selectionColor; 29 | background: $selectionBackgroundColor; 30 | text-shadow: none; 31 | } 32 | 33 | .reveal .slides section, 34 | .reveal .slides section>section { 35 | line-height: 1.3; 36 | font-weight: inherit; 37 | } 38 | 39 | /********************************************* 40 | * HEADERS 41 | *********************************************/ 42 | 43 | .reveal h1, 44 | .reveal h2, 45 | .reveal h3, 46 | .reveal h4, 47 | .reveal h5, 48 | .reveal h6 { 49 | margin: $headingMargin; 50 | color: $headingColor; 51 | 52 | font-family: $headingFont; 53 | font-weight: $headingFontWeight; 54 | line-height: $headingLineHeight; 55 | letter-spacing: $headingLetterSpacing; 56 | 57 | text-transform: $headingTextTransform; 58 | text-shadow: $headingTextShadow; 59 | 60 | word-wrap: break-word; 61 | } 62 | 63 | .reveal h1 {font-size: $heading1Size; } 64 | .reveal h2 {font-size: $heading2Size; } 65 | .reveal h3 {font-size: $heading3Size; } 66 | .reveal h4 {font-size: $heading4Size; } 67 | 68 | .reveal h1 { 69 | text-shadow: $heading1TextShadow; 70 | } 71 | 72 | 73 | /********************************************* 74 | * OTHER 75 | *********************************************/ 76 | 77 | .reveal p { 78 | margin: $blockMargin 0; 79 | line-height: 1.3; 80 | } 81 | 82 | /* Remove trailing margins after titles */ 83 | .reveal h1:last-child, 84 | .reveal h2:last-child, 85 | .reveal h3:last-child, 86 | .reveal h4:last-child, 87 | .reveal h5:last-child, 88 | .reveal h6:last-child { 89 | margin-bottom: 0; 90 | } 91 | 92 | /* Ensure certain elements are never larger than the slide itself */ 93 | .reveal img, 94 | .reveal video, 95 | .reveal iframe { 96 | max-width: 95%; 97 | max-height: 95%; 98 | } 99 | .reveal strong, 100 | .reveal b { 101 | font-weight: bold; 102 | } 103 | 104 | .reveal em { 105 | font-style: italic; 106 | } 107 | 108 | .reveal ol, 109 | .reveal dl, 110 | .reveal ul { 111 | display: inline-block; 112 | 113 | text-align: left; 114 | margin: 0 0 0 1em; 115 | } 116 | 117 | .reveal ol { 118 | list-style-type: decimal; 119 | } 120 | 121 | .reveal ul { 122 | list-style-type: disc; 123 | } 124 | 125 | .reveal ul ul { 126 | list-style-type: square; 127 | } 128 | 129 | .reveal ul ul ul { 130 | list-style-type: circle; 131 | } 132 | 133 | .reveal ul ul, 134 | .reveal ul ol, 135 | .reveal ol ol, 136 | .reveal ol ul { 137 | display: block; 138 | margin-left: 40px; 139 | } 140 | 141 | .reveal dt { 142 | font-weight: bold; 143 | } 144 | 145 | .reveal dd { 146 | margin-left: 40px; 147 | } 148 | 149 | .reveal blockquote { 150 | display: block; 151 | position: relative; 152 | width: 70%; 153 | margin: $blockMargin auto; 154 | padding: 5px; 155 | 156 | font-style: italic; 157 | background: rgba(255, 255, 255, 0.05); 158 | box-shadow: 0px 0px 2px rgba(0,0,0,0.2); 159 | } 160 | .reveal blockquote p:first-child, 161 | .reveal blockquote p:last-child { 162 | display: inline-block; 163 | } 164 | 165 | .reveal q { 166 | font-style: italic; 167 | } 168 | 169 | .reveal pre { 170 | display: block; 171 | position: relative; 172 | width: 90%; 173 | margin: $blockMargin auto; 174 | 175 | text-align: left; 176 | font-size: 0.55em; 177 | font-family: $codeFont; 178 | line-height: 1.2em; 179 | 180 | word-wrap: break-word; 181 | 182 | box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); 183 | } 184 | 185 | .reveal code { 186 | font-family: $codeFont; 187 | text-transform: none; 188 | } 189 | 190 | .reveal pre code { 191 | display: block; 192 | padding: 5px; 193 | overflow: auto; 194 | max-height: 400px; 195 | word-wrap: normal; 196 | } 197 | 198 | .reveal table { 199 | margin: auto; 200 | border-collapse: collapse; 201 | border-spacing: 0; 202 | } 203 | 204 | .reveal table th { 205 | font-weight: bold; 206 | } 207 | 208 | .reveal table th, 209 | .reveal table td { 210 | text-align: left; 211 | padding: 0.2em 0.5em 0.2em 0.5em; 212 | border-bottom: 1px solid; 213 | } 214 | 215 | .reveal table th[align="center"], 216 | .reveal table td[align="center"] { 217 | text-align: center; 218 | } 219 | 220 | .reveal table th[align="right"], 221 | .reveal table td[align="right"] { 222 | text-align: right; 223 | } 224 | 225 | .reveal table tbody tr:last-child th, 226 | .reveal table tbody tr:last-child td { 227 | border-bottom: none; 228 | } 229 | 230 | .reveal sup { 231 | vertical-align: super; 232 | font-size: smaller; 233 | } 234 | .reveal sub { 235 | vertical-align: sub; 236 | font-size: smaller; 237 | } 238 | 239 | .reveal small { 240 | display: inline-block; 241 | font-size: 0.6em; 242 | line-height: 1.2em; 243 | vertical-align: top; 244 | } 245 | 246 | .reveal small * { 247 | vertical-align: top; 248 | } 249 | 250 | .reveal img { 251 | margin: $blockMargin 0; 252 | } 253 | 254 | 255 | /********************************************* 256 | * LINKS 257 | *********************************************/ 258 | 259 | .reveal a { 260 | color: $linkColor; 261 | text-decoration: none; 262 | transition: color .15s ease; 263 | } 264 | .reveal a:hover { 265 | color: $linkColorHover; 266 | text-shadow: none; 267 | border: none; 268 | } 269 | 270 | .reveal .roll span:after { 271 | color: #fff; 272 | background: darken( $linkColor, 15% ); 273 | } 274 | 275 | 276 | /********************************************* 277 | * Frame helper 278 | *********************************************/ 279 | 280 | .reveal .r-frame { 281 | border: 4px solid $mainColor; 282 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); 283 | } 284 | 285 | .reveal a .r-frame { 286 | transition: all .15s linear; 287 | } 288 | 289 | .reveal a:hover .r-frame { 290 | border-color: $linkColor; 291 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); 292 | } 293 | 294 | 295 | /********************************************* 296 | * NAVIGATION CONTROLS 297 | *********************************************/ 298 | 299 | .reveal .controls { 300 | color: $linkColor; 301 | } 302 | 303 | 304 | /********************************************* 305 | * PROGRESS BAR 306 | *********************************************/ 307 | 308 | .reveal .progress { 309 | background: rgba(0,0,0,0.2); 310 | color: $linkColor; 311 | } 312 | 313 | /********************************************* 314 | * PRINT BACKGROUND 315 | *********************************************/ 316 | @media print { 317 | .backgrounds { 318 | background-color: $backgroundColor; 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /js/search/plugin.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Handles finding a text string anywhere in the slides and showing the next occurrence to the user 3 | * by navigatating to that slide and highlighting it. 4 | * 5 | * @author Jon Snyder , February 2013 6 | */ 7 | 8 | const Plugin = () => { 9 | 10 | // The reveal.js instance this plugin is attached to 11 | let deck; 12 | 13 | let searchElement; 14 | let searchButton; 15 | let searchInput; 16 | 17 | let matchedSlides; 18 | let currentMatchedIndex; 19 | let searchboxDirty; 20 | let hilitor; 21 | 22 | function render() { 23 | 24 | searchElement = document.createElement( 'div' ); 25 | searchElement.classList.add( 'searchbox' ); 26 | searchElement.style.position = 'absolute'; 27 | searchElement.style.top = '10px'; 28 | searchElement.style.right = '10px'; 29 | searchElement.style.zIndex = 10; 30 | 31 | //embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/: 32 | searchElement.innerHTML = ` 33 | `; 34 | 35 | searchInput = searchElement.querySelector( '.searchinput' ); 36 | searchInput.style.width = '240px'; 37 | searchInput.style.fontSize = '14px'; 38 | searchInput.style.padding = '4px 6px'; 39 | searchInput.style.color = '#000'; 40 | searchInput.style.background = '#fff'; 41 | searchInput.style.borderRadius = '2px'; 42 | searchInput.style.border = '0'; 43 | searchInput.style.outline = '0'; 44 | searchInput.style.boxShadow = '0 2px 18px rgba(0, 0, 0, 0.2)'; 45 | searchInput.style['-webkit-appearance'] = 'none'; 46 | 47 | deck.getRevealElement().appendChild( searchElement ); 48 | 49 | // searchButton.addEventListener( 'click', function(event) { 50 | // doSearch(); 51 | // }, false ); 52 | 53 | searchInput.addEventListener( 'keyup', function( event ) { 54 | switch (event.keyCode) { 55 | case 13: 56 | event.preventDefault(); 57 | doSearch(); 58 | searchboxDirty = false; 59 | break; 60 | default: 61 | searchboxDirty = true; 62 | } 63 | }, false ); 64 | 65 | closeSearch(); 66 | 67 | } 68 | 69 | function openSearch() { 70 | if( !searchElement ) render(); 71 | 72 | searchElement.style.display = 'inline'; 73 | searchInput.focus(); 74 | searchInput.select(); 75 | } 76 | 77 | function closeSearch() { 78 | if( !searchElement ) render(); 79 | 80 | searchElement.style.display = 'none'; 81 | if(hilitor) hilitor.remove(); 82 | } 83 | 84 | function toggleSearch() { 85 | if( !searchElement ) render(); 86 | 87 | if (searchElement.style.display !== 'inline') { 88 | openSearch(); 89 | } 90 | else { 91 | closeSearch(); 92 | } 93 | } 94 | 95 | function doSearch() { 96 | //if there's been a change in the search term, perform a new search: 97 | if (searchboxDirty) { 98 | var searchstring = searchInput.value; 99 | 100 | if (searchstring === '') { 101 | if(hilitor) hilitor.remove(); 102 | matchedSlides = null; 103 | } 104 | else { 105 | //find the keyword amongst the slides 106 | hilitor = new Hilitor("slidecontent"); 107 | matchedSlides = hilitor.apply(searchstring); 108 | currentMatchedIndex = 0; 109 | } 110 | } 111 | 112 | if (matchedSlides) { 113 | //navigate to the next slide that has the keyword, wrapping to the first if necessary 114 | if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) { 115 | currentMatchedIndex = 0; 116 | } 117 | if (matchedSlides.length > currentMatchedIndex) { 118 | deck.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v); 119 | currentMatchedIndex++; 120 | } 121 | } 122 | } 123 | 124 | // Original JavaScript code by Chirp Internet: www.chirp.com.au 125 | // Please acknowledge use of this code by including this header. 126 | // 2/2013 jon: modified regex to display any match, not restricted to word boundaries. 127 | function Hilitor(id, tag) { 128 | 129 | var targetNode = document.getElementById(id) || document.body; 130 | var hiliteTag = tag || "EM"; 131 | var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$"); 132 | var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"]; 133 | var wordColor = []; 134 | var colorIdx = 0; 135 | var matchRegex = ""; 136 | var matchingSlides = []; 137 | 138 | this.setRegex = function(input) 139 | { 140 | input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|"); 141 | matchRegex = new RegExp("(" + input + ")","i"); 142 | } 143 | 144 | this.getRegex = function() 145 | { 146 | return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " "); 147 | } 148 | 149 | // recursively apply word highlighting 150 | this.hiliteWords = function(node) 151 | { 152 | if(node == undefined || !node) return; 153 | if(!matchRegex) return; 154 | if(skipTags.test(node.nodeName)) return; 155 | 156 | if(node.hasChildNodes()) { 157 | for(var i=0; i < node.childNodes.length; i++) 158 | this.hiliteWords(node.childNodes[i]); 159 | } 160 | if(node.nodeType == 3) { // NODE_TEXT 161 | var nv, regs; 162 | if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) { 163 | //find the slide's section element and save it in our list of matching slides 164 | var secnode = node; 165 | while (secnode != null && secnode.nodeName != 'SECTION') { 166 | secnode = secnode.parentNode; 167 | } 168 | 169 | var slideIndex = deck.getIndices(secnode); 170 | var slidelen = matchingSlides.length; 171 | var alreadyAdded = false; 172 | for (var i=0; i < slidelen; i++) { 173 | if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) { 174 | alreadyAdded = true; 175 | } 176 | } 177 | if (! alreadyAdded) { 178 | matchingSlides.push(slideIndex); 179 | } 180 | 181 | if(!wordColor[regs[0].toLowerCase()]) { 182 | wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length]; 183 | } 184 | 185 | var match = document.createElement(hiliteTag); 186 | match.appendChild(document.createTextNode(regs[0])); 187 | match.style.backgroundColor = wordColor[regs[0].toLowerCase()]; 188 | match.style.fontStyle = "inherit"; 189 | match.style.color = "#000"; 190 | 191 | var after = node.splitText(regs.index); 192 | after.nodeValue = after.nodeValue.substring(regs[0].length); 193 | node.parentNode.insertBefore(match, after); 194 | } 195 | } 196 | }; 197 | 198 | // remove highlighting 199 | this.remove = function() 200 | { 201 | var arr = document.getElementsByTagName(hiliteTag); 202 | var el; 203 | while(arr.length && (el = arr[0])) { 204 | el.parentNode.replaceChild(el.firstChild, el); 205 | } 206 | }; 207 | 208 | // start highlighting at target node 209 | this.apply = function(input) 210 | { 211 | if(input == undefined || !input) return; 212 | this.remove(); 213 | this.setRegex(input); 214 | this.hiliteWords(targetNode); 215 | return matchingSlides; 216 | }; 217 | 218 | } 219 | 220 | return { 221 | 222 | id: 'search', 223 | 224 | init: reveal => { 225 | 226 | deck = reveal; 227 | deck.registerKeyboardShortcut( 'CTRL + Shift + F', 'Search' ); 228 | 229 | document.addEventListener( 'keydown', function( event ) { 230 | if( event.key == "F" && (event.ctrlKey || event.metaKey) ) { //Control+Shift+f 231 | event.preventDefault(); 232 | toggleSearch(); 233 | } 234 | }, false ); 235 | 236 | }, 237 | 238 | open: openSearch 239 | 240 | } 241 | }; 242 | 243 | export default Plugin; -------------------------------------------------------------------------------- /slides/disco-prelysium/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Juan Uys - Disco PRElysium 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | 48 |
49 |

Disco Pre-lysium

50 |

If Disco Elysium was prototyped today.

51 | Disco Elysium official artwork, Copyright ZA/UM 52 |
53 | 54 |
55 |

In this exercise, I'll simulate the planning stage of Disco Elysium using a variety of prototyping techniques:

56 |
    57 |
  • wireframing
  • 58 |
  • sketching
  • 59 |
  • narrative prototyping
  • 60 |
61 |
62 | 63 |
64 |

wireframing

65 |

Here we try a bunch of screen layouts, colour-coded as follows:

66 |
    67 |
  • dialogue
  • 68 |
  • inventory
  • 69 |
  • world
  • 70 |
71 |
72 | 73 |
74 |

wireframing

75 |

76 | On the left, we split gameplay and conversation down the middle, but it feels like we're giving too much space to the conversation. 77 | We try to make it smaller, but is it too small? 78 |

79 | wireframe 1 80 | 81 |
    82 |
  • dialogue
  • 83 |
  • inventory
  • 84 |
  • world
  • 85 |
86 |
87 | 88 |
89 |

wireframing

90 |

91 | Let's try thirds. That looks nice. OK, how about inventory? On the left below gameplay, or on the right below the conversation? 92 |

93 | wireframe 2 94 | 95 |
    96 |
  • dialogue
  • 97 |
  • inventory
  • 98 |
  • world
  • 99 |
100 |
101 | 102 |
103 |

wireframing

104 |

105 | Definitely below conversation, so we can have a nice, large gameplay area. But let's not be all squares. How about a trapezoid? 106 | And a ...bit... more space for conversation. OK, that looks good. 107 |

108 | wireframe 3 109 | 110 |
    111 |
  • dialogue
  • 112 |
  • inventory
  • 113 |
  • world
  • 114 |
115 |
116 | 117 |
118 |

wireframing

119 |

120 | Right, that's a good layout. Let's see some rough concept art in it, shall we? 121 |

122 | wireframe final choice 123 |
124 | 125 |
126 |

sketching

127 |

128 | Dark and gritty, just like the protagonist. 129 |

130 | Rough sketch of game world and some characters 131 |
132 | 133 |
134 | Robert Kurvitz
135 | Robert Kurvitz, lead game designer 136 | 137 |

138 | OK, stop. 139 | I know this is based on my novel and all, but is there a way we can test the dialogue before we spend LOADS of time drawing stuff and coding something? 140 |

141 |

142 | I mean, we already spent LOADS of time on the wireframes... 143 |

144 |
145 | 146 |
147 |

narrative prototyping

148 | 149 |
150 |

151 | We've got just the tool. 152 |

153 |

Twine.

154 |
155 | 156 |
157 |

You mean this?

158 | The wrong kind of Twine 159 |
160 | 161 |
162 |

163 | Not THAT kind of Twine... 164 |

165 |
166 |
167 | 168 |
169 |

narrative prototyping

170 | The right kind of Twine 171 |
172 | twinery.org 173 |
174 | 175 |
176 |

This next section is Copyright © Alexei Pepers / @ampepers

177 | 178 |

Don't skip ahead. Click the red Continue button to follow the story...

179 |
180 | 181 |
182 | 183 |
184 | 185 |
186 |

FIN

187 |
188 |
189 | (back to the blog) 190 |
191 | 192 |
193 |
194 | 195 | 196 | -------------------------------------------------------------------------------- /js/zoom/plugin.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * reveal.js Zoom plugin 3 | */ 4 | const Plugin = { 5 | 6 | id: 'zoom', 7 | 8 | init: function( reveal ) { 9 | 10 | reveal.getRevealElement().addEventListener( 'mousedown', function( event ) { 11 | var defaultModifier = /Linux/.test( window.navigator.platform ) ? 'ctrl' : 'alt'; 12 | 13 | var modifier = ( reveal.getConfig().zoomKey ? reveal.getConfig().zoomKey : defaultModifier ) + 'Key'; 14 | var zoomLevel = ( reveal.getConfig().zoomLevel ? reveal.getConfig().zoomLevel : 2 ); 15 | 16 | if( event[ modifier ] && !reveal.isOverview() ) { 17 | event.preventDefault(); 18 | 19 | zoom.to({ 20 | x: event.clientX, 21 | y: event.clientY, 22 | scale: zoomLevel, 23 | pan: false 24 | }); 25 | } 26 | } ); 27 | 28 | } 29 | 30 | }; 31 | 32 | export default () => Plugin; 33 | 34 | /*! 35 | * zoom.js 0.3 (modified for use with reveal.js) 36 | * http://lab.hakim.se/zoom-js 37 | * MIT licensed 38 | * 39 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se 40 | */ 41 | var zoom = (function(){ 42 | 43 | // The current zoom level (scale) 44 | var level = 1; 45 | 46 | // The current mouse position, used for panning 47 | var mouseX = 0, 48 | mouseY = 0; 49 | 50 | // Timeout before pan is activated 51 | var panEngageTimeout = -1, 52 | panUpdateInterval = -1; 53 | 54 | // Check for transform support so that we can fallback otherwise 55 | var supportsTransforms = 'WebkitTransform' in document.body.style || 56 | 'MozTransform' in document.body.style || 57 | 'msTransform' in document.body.style || 58 | 'OTransform' in document.body.style || 59 | 'transform' in document.body.style; 60 | 61 | if( supportsTransforms ) { 62 | // The easing that will be applied when we zoom in/out 63 | document.body.style.transition = 'transform 0.8s ease'; 64 | document.body.style.OTransition = '-o-transform 0.8s ease'; 65 | document.body.style.msTransition = '-ms-transform 0.8s ease'; 66 | document.body.style.MozTransition = '-moz-transform 0.8s ease'; 67 | document.body.style.WebkitTransition = '-webkit-transform 0.8s ease'; 68 | } 69 | 70 | // Zoom out if the user hits escape 71 | document.addEventListener( 'keyup', function( event ) { 72 | if( level !== 1 && event.keyCode === 27 ) { 73 | zoom.out(); 74 | } 75 | } ); 76 | 77 | // Monitor mouse movement for panning 78 | document.addEventListener( 'mousemove', function( event ) { 79 | if( level !== 1 ) { 80 | mouseX = event.clientX; 81 | mouseY = event.clientY; 82 | } 83 | } ); 84 | 85 | /** 86 | * Applies the CSS required to zoom in, prefers the use of CSS3 87 | * transforms but falls back on zoom for IE. 88 | * 89 | * @param {Object} rect 90 | * @param {Number} scale 91 | */ 92 | function magnify( rect, scale ) { 93 | 94 | var scrollOffset = getScrollOffset(); 95 | 96 | // Ensure a width/height is set 97 | rect.width = rect.width || 1; 98 | rect.height = rect.height || 1; 99 | 100 | // Center the rect within the zoomed viewport 101 | rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2; 102 | rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2; 103 | 104 | if( supportsTransforms ) { 105 | // Reset 106 | if( scale === 1 ) { 107 | document.body.style.transform = ''; 108 | document.body.style.OTransform = ''; 109 | document.body.style.msTransform = ''; 110 | document.body.style.MozTransform = ''; 111 | document.body.style.WebkitTransform = ''; 112 | } 113 | // Scale 114 | else { 115 | var origin = scrollOffset.x +'px '+ scrollOffset.y +'px', 116 | transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')'; 117 | 118 | document.body.style.transformOrigin = origin; 119 | document.body.style.OTransformOrigin = origin; 120 | document.body.style.msTransformOrigin = origin; 121 | document.body.style.MozTransformOrigin = origin; 122 | document.body.style.WebkitTransformOrigin = origin; 123 | 124 | document.body.style.transform = transform; 125 | document.body.style.OTransform = transform; 126 | document.body.style.msTransform = transform; 127 | document.body.style.MozTransform = transform; 128 | document.body.style.WebkitTransform = transform; 129 | } 130 | } 131 | else { 132 | // Reset 133 | if( scale === 1 ) { 134 | document.body.style.position = ''; 135 | document.body.style.left = ''; 136 | document.body.style.top = ''; 137 | document.body.style.width = ''; 138 | document.body.style.height = ''; 139 | document.body.style.zoom = ''; 140 | } 141 | // Scale 142 | else { 143 | document.body.style.position = 'relative'; 144 | document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px'; 145 | document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px'; 146 | document.body.style.width = ( scale * 100 ) + '%'; 147 | document.body.style.height = ( scale * 100 ) + '%'; 148 | document.body.style.zoom = scale; 149 | } 150 | } 151 | 152 | level = scale; 153 | 154 | if( document.documentElement.classList ) { 155 | if( level !== 1 ) { 156 | document.documentElement.classList.add( 'zoomed' ); 157 | } 158 | else { 159 | document.documentElement.classList.remove( 'zoomed' ); 160 | } 161 | } 162 | } 163 | 164 | /** 165 | * Pan the document when the mosue cursor approaches the edges 166 | * of the window. 167 | */ 168 | function pan() { 169 | var range = 0.12, 170 | rangeX = window.innerWidth * range, 171 | rangeY = window.innerHeight * range, 172 | scrollOffset = getScrollOffset(); 173 | 174 | // Up 175 | if( mouseY < rangeY ) { 176 | window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) ); 177 | } 178 | // Down 179 | else if( mouseY > window.innerHeight - rangeY ) { 180 | window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) ); 181 | } 182 | 183 | // Left 184 | if( mouseX < rangeX ) { 185 | window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y ); 186 | } 187 | // Right 188 | else if( mouseX > window.innerWidth - rangeX ) { 189 | window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y ); 190 | } 191 | } 192 | 193 | function getScrollOffset() { 194 | return { 195 | x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset, 196 | y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset 197 | } 198 | } 199 | 200 | return { 201 | /** 202 | * Zooms in on either a rectangle or HTML element. 203 | * 204 | * @param {Object} options 205 | * - element: HTML element to zoom in on 206 | * OR 207 | * - x/y: coordinates in non-transformed space to zoom in on 208 | * - width/height: the portion of the screen to zoom in on 209 | * - scale: can be used instead of width/height to explicitly set scale 210 | */ 211 | to: function( options ) { 212 | 213 | // Due to an implementation limitation we can't zoom in 214 | // to another element without zooming out first 215 | if( level !== 1 ) { 216 | zoom.out(); 217 | } 218 | else { 219 | options.x = options.x || 0; 220 | options.y = options.y || 0; 221 | 222 | // If an element is set, that takes precedence 223 | if( !!options.element ) { 224 | // Space around the zoomed in element to leave on screen 225 | var padding = 20; 226 | var bounds = options.element.getBoundingClientRect(); 227 | 228 | options.x = bounds.left - padding; 229 | options.y = bounds.top - padding; 230 | options.width = bounds.width + ( padding * 2 ); 231 | options.height = bounds.height + ( padding * 2 ); 232 | } 233 | 234 | // If width/height values are set, calculate scale from those values 235 | if( options.width !== undefined && options.height !== undefined ) { 236 | options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 ); 237 | } 238 | 239 | if( options.scale > 1 ) { 240 | options.x *= options.scale; 241 | options.y *= options.scale; 242 | 243 | magnify( options, options.scale ); 244 | 245 | if( options.pan !== false ) { 246 | 247 | // Wait with engaging panning as it may conflict with the 248 | // zoom transition 249 | panEngageTimeout = setTimeout( function() { 250 | panUpdateInterval = setInterval( pan, 1000 / 60 ); 251 | }, 800 ); 252 | 253 | } 254 | } 255 | } 256 | }, 257 | 258 | /** 259 | * Resets the document zoom state to its default. 260 | */ 261 | out: function() { 262 | clearTimeout( panEngageTimeout ); 263 | clearInterval( panUpdateInterval ); 264 | 265 | magnify( { x: 0, y: 0 }, 1 ); 266 | 267 | level = 1; 268 | }, 269 | 270 | // Alias 271 | magnify: function( options ) { this.to( options ) }, 272 | reset: function() { this.out() }, 273 | 274 | zoomLevel: function() { 275 | return level; 276 | } 277 | } 278 | 279 | })(); 280 | -------------------------------------------------------------------------------- /js/search/search.esm.js: -------------------------------------------------------------------------------- 1 | var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(t,e,n){return t(n={path:e,exports:{},require:function(t,e){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==e&&n.path)}},n.exports),n.exports}var n=function(t){return t&&t.Math==Math&&t},r=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof t&&t)||Function("return this")(),o=function(t){try{return!!t()}catch(t){return!0}},i=!o((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),c=function(t){return"object"==typeof t?null!==t:"function"==typeof t},u=r.document,a=c(u)&&c(u.createElement),l=!i&&!o((function(){return 7!=Object.defineProperty((t="div",a?u.createElement(t):{}),"a",{get:function(){return 7}}).a;var t})),f=function(t){if(!c(t))throw TypeError(String(t)+" is not an object");return t},s=function(t,e){if(!c(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!c(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!c(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!c(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")},p=Object.defineProperty,g={f:i?p:function(t,e,n){if(f(t),e=s(e,!0),f(n),l)try{return p(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},d=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},h=i?function(t,e,n){return g.f(t,e,d(1,n))}:function(t,e,n){return t[e]=n,t},y=function(t,e){try{h(r,t,e)}catch(n){r[t]=e}return e},v=r["__core-js_shared__"]||y("__core-js_shared__",{}),b=e((function(t){(t.exports=function(t,e){return v[t]||(v[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.6.5",mode:"global",copyright:"© 2020 Denis Pushkarev (zloirock.ru)"})})),x={}.hasOwnProperty,E=function(t,e){return x.call(t,e)},m=0,S=Math.random(),w=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++m+S).toString(36)},O=!!Object.getOwnPropertySymbols&&!o((function(){return!String(Symbol())})),R=O&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,_=b("wks"),T=r.Symbol,j=R?T:T&&T.withoutSetter||w,P=function(t){return E(_,t)||(O&&E(T,t)?_[t]=T[t]:_[t]=j("Symbol."+t)),_[t]},I={};I[P("toStringTag")]="z";var C="[object z]"===String(I),N=Function.toString;"function"!=typeof v.inspectSource&&(v.inspectSource=function(t){return N.call(t)});var A,k,$,L,M=v.inspectSource,U=r.WeakMap,D="function"==typeof U&&/native code/.test(M(U)),F=b("keys"),K={},z=r.WeakMap;if(D){var B=new z,W=B.get,q=B.has,G=B.set;A=function(t,e){return G.call(B,t,e),e},k=function(t){return W.call(B,t)||{}},$=function(t){return q.call(B,t)}}else{var V=F[L="state"]||(F[L]=w(L));K[V]=!0,A=function(t,e){return h(t,V,e),e},k=function(t){return E(t,V)?t[V]:{}},$=function(t){return E(t,V)}}var Y={set:A,get:k,has:$,enforce:function(t){return $(t)?k(t):A(t,{})},getterFor:function(t){return function(e){var n;if(!c(e)||(n=k(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}}},X=e((function(t){var e=Y.get,n=Y.enforce,o=String(String).split("String");(t.exports=function(t,e,i,c){var u=!!c&&!!c.unsafe,a=!!c&&!!c.enumerable,l=!!c&&!!c.noTargetGet;"function"==typeof i&&("string"!=typeof e||E(i,"name")||h(i,"name",e),n(i).source=o.join("string"==typeof e?e:"")),t!==r?(u?!l&&t[e]&&(a=!0):delete t[e],a?t[e]=i:h(t,e,i)):a?t[e]=i:y(e,i)})(Function.prototype,"toString",(function(){return"function"==typeof this&&e(this).source||M(this)}))})),H={}.toString,J=function(t){return H.call(t).slice(8,-1)},Q=P("toStringTag"),Z="Arguments"==J(function(){return arguments}()),tt=C?J:function(t){var e,n,r;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=Object(t),Q))?n:Z?J(e):"Object"==(r=J(e))&&"function"==typeof e.callee?"Arguments":r},et=C?{}.toString:function(){return"[object "+tt(this)+"]"};C||X(Object.prototype,"toString",et,{unsafe:!0});var nt=/#|\.prototype\./,rt=function(t,e){var n=it[ot(t)];return n==ut||n!=ct&&("function"==typeof e?o(e):!!e)},ot=rt.normalize=function(t){return String(t).replace(nt,".").toLowerCase()},it=rt.data={},ct=rt.NATIVE="N",ut=rt.POLYFILL="P",at=rt,lt=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{(t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(n,[]),e=n instanceof Array}catch(t){}return function(n,r){return f(n),function(t){if(!c(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype")}(r),e?t.call(n,r):n.__proto__=r,n}}():void 0),ft="".split,st=o((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==J(t)?ft.call(t,""):Object(t)}:Object,pt=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t},gt=function(t){return st(pt(t))},dt=Math.ceil,ht=Math.floor,yt=function(t){return isNaN(t=+t)?0:(t>0?ht:dt)(t)},vt=Math.min,bt=function(t){return t>0?vt(yt(t),9007199254740991):0},xt=Math.max,Et=Math.min,mt=function(t){return function(e,n,r){var o,i=gt(e),c=bt(i.length),u=function(t,e){var n=yt(t);return n<0?xt(n+e,0):Et(n,e)}(r,c);if(t&&n!=n){for(;c>u;)if((o=i[u++])!=o)return!0}else for(;c>u;u++)if((t||u in i)&&i[u]===n)return t||u||0;return!t&&-1}},St={includes:mt(!0),indexOf:mt(!1)}.indexOf,wt=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"].concat("length","prototype"),Ot={f:Object.getOwnPropertyNames||function(t){return function(t,e){var n,r=gt(t),o=0,i=[];for(n in r)!E(K,n)&&E(r,n)&&i.push(n);for(;e.length>o;)E(r,n=e[o++])&&(~St(i,n)||i.push(n));return i}(t,wt)}},Rt=P("match"),_t=function(){var t=f(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e};function Tt(t,e){return RegExp(t,e)}var jt={UNSUPPORTED_Y:o((function(){var t=Tt("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),BROKEN_CARET:o((function(){var t=Tt("^r","gy");return t.lastIndex=2,null!=t.exec("str")}))},Pt=r,It=function(t){return"function"==typeof t?t:void 0},Ct=function(t,e){return arguments.length<2?It(Pt[t])||It(r[t]):Pt[t]&&Pt[t][e]||r[t]&&r[t][e]},Nt=P("species"),At=g.f,kt=Ot.f,$t=Y.set,Lt=P("match"),Mt=r.RegExp,Ut=Mt.prototype,Dt=/a/g,Ft=/a/g,Kt=new Mt(Dt)!==Dt,zt=jt.UNSUPPORTED_Y;if(i&&at("RegExp",!Kt||zt||o((function(){return Ft[Lt]=!1,Mt(Dt)!=Dt||Mt(Ft)==Ft||"/a/i"!=Mt(Dt,"i")})))){for(var Bt=function(t,e){var n,r,o,i=this instanceof Bt,u=c(n=t)&&(void 0!==(r=n[Rt])?!!r:"RegExp"==J(n)),a=void 0===e;if(!i&&u&&t.constructor===Bt&&a)return t;Kt?u&&!a&&(t=t.source):t instanceof Bt&&(a&&(e=_t.call(t)),t=t.source),zt&&(o=!!e&&e.indexOf("y")>-1)&&(e=e.replace(/y/g,""));var l,f,s,p,g,d=(l=Kt?new Mt(t,e):Mt(t,e),f=i?this:Ut,s=Bt,lt&&"function"==typeof(p=f.constructor)&&p!==s&&c(g=p.prototype)&&g!==s.prototype&<(l,g),l);return zt&&o&&$t(d,{sticky:o}),d},Wt=function(t){t in Bt||At(Bt,t,{configurable:!0,get:function(){return Mt[t]},set:function(e){Mt[t]=e}})},qt=kt(Mt),Gt=0;qt.length>Gt;)Wt(qt[Gt++]);Ut.constructor=Bt,Bt.prototype=Ut,X(r,"RegExp",Bt)}!function(t){var e=Ct(t),n=g.f;i&&e&&!e[Nt]&&n(e,Nt,{configurable:!0,get:function(){return this}})}("RegExp");var Vt={}.propertyIsEnumerable,Yt=Object.getOwnPropertyDescriptor,Xt={f:Yt&&!Vt.call({1:2},1)?function(t){var e=Yt(this,t);return!!e&&e.enumerable}:Vt},Ht=Object.getOwnPropertyDescriptor,Jt={f:i?Ht:function(t,e){if(t=gt(t),e=s(e,!0),l)try{return Ht(t,e)}catch(t){}if(E(t,e))return d(!Xt.f.call(t,e),t[e])}},Qt={f:Object.getOwnPropertySymbols},Zt=Ct("Reflect","ownKeys")||function(t){var e=Ot.f(f(t)),n=Qt.f;return n?e.concat(n(t)):e},te=function(t,e){for(var n=Zt(e),r=g.f,o=Jt.f,i=0;i0&&(!i.multiline||i.multiline&&"\n"!==t[i.lastIndex-1])&&(a="(?: "+a+")",f=" "+f,l++),n=new RegExp("^(?:"+a+")",u)),ue&&(n=new RegExp("^"+a+"$(?!\\s)",u)),ie&&(e=i.lastIndex),r=ne.call(c?n:i,f),c?r?(r.input=r.input.slice(l),r[0]=r[0].slice(l),r.index=i.lastIndex,i.lastIndex+=r[0].length):i.lastIndex=0:ie&&r&&(i.lastIndex=i.global?r.index+r[0].length:e),ue&&r&&r.length>1&&re.call(r[0],n,(function(){for(o=1;o")})),he="$0"==="a".replace(/./,"$0"),ye=P("replace"),ve=!!/./[ye]&&""===/./[ye]("a","$0"),be=!o((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]})),xe=function(t){return function(e,n){var r,o,i=String(pt(e)),c=yt(n),u=i.length;return c<0||c>=u?t?"":void 0:(r=i.charCodeAt(c))<55296||r>56319||c+1===u||(o=i.charCodeAt(c+1))<56320||o>57343?t?i.charAt(c):r:t?i.slice(c,c+2):o-56320+(r-55296<<10)+65536}},Ee={codeAt:xe(!1),charAt:xe(!0)}.charAt,me=function(t,e,n){return e+(n?Ee(t,e).length:1)},Se=function(t,e){var n=t.exec;if("function"==typeof n){var r=n.call(t,e);if("object"!=typeof r)throw TypeError("RegExp exec method returned something other than an Object or null");return r}if("RegExp"!==J(t))throw TypeError("RegExp#exec called on incompatible receiver");return ae.call(t,e)},we=Math.max,Oe=Math.min,Re=Math.floor,_e=/\$([$&'`]|\d\d?|<[^>]*>)/g,Te=/\$([$&'`]|\d\d?)/g;!function(t,e,n,r){var i=P(t),c=!o((function(){var e={};return e[i]=function(){return 7},7!=""[t](e)})),u=c&&!o((function(){var e=!1,n=/a/;return"split"===t&&((n={}).constructor={},n.constructor[ge]=function(){return n},n.flags="",n[i]=/./[i]),n.exec=function(){return e=!0,null},n[i](""),!e}));if(!c||!u||"replace"===t&&(!de||!he||ve)||"split"===t&&!be){var a=/./[i],l=n(i,""[t],(function(t,e,n,r,o){return e.exec===ae?c&&!o?{done:!0,value:a.call(e,n,r)}:{done:!0,value:t.call(n,e,r)}:{done:!1}}),{REPLACE_KEEPS_$0:he,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:ve}),f=l[0],s=l[1];X(String.prototype,t,f),X(RegExp.prototype,i,2==e?function(t,e){return s.call(t,this,e)}:function(t){return s.call(t,this)})}r&&h(RegExp.prototype[i],"sham",!0)}("replace",2,(function(t,e,n,r){var o=r.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,i=r.REPLACE_KEEPS_$0,c=o?"$":"$0";return[function(n,r){var o=pt(this),i=null==n?void 0:n[t];return void 0!==i?i.call(n,o,r):e.call(String(o),n,r)},function(t,r){if(!o&&i||"string"==typeof r&&-1===r.indexOf(c)){var a=n(e,t,this,r);if(a.done)return a.value}var l=f(t),s=String(this),p="function"==typeof r;p||(r=String(r));var g=l.global;if(g){var d=l.unicode;l.lastIndex=0}for(var h=[];;){var y=Se(l,s);if(null===y)break;if(h.push(y),!g)break;""===String(y[0])&&(l.lastIndex=me(s,bt(l.lastIndex),d))}for(var v,b="",x=0,E=0;E=x&&(b+=s.slice(x,S)+T,x=S+m.length)}return b+s.slice(x)}];function u(t,n,r,o,i,c){var u=r+t.length,a=o.length,l=Te;return void 0!==i&&(i=Object(pt(i)),l=_e),e.call(c,l,(function(e,c){var l;switch(c.charAt(0)){case"$":return"$";case"&":return t;case"`":return n.slice(0,r);case"'":return n.slice(u);case"<":l=i[c.slice(1,-1)];break;default:var f=+c;if(0===f)return e;if(f>a){var s=Re(f/10);return 0===s?e:s<=a?void 0===o[s-1]?c.charAt(1):o[s-1]+c.charAt(1):e}l=o[f-1]}return void 0===l?"":l}))}}));export default function(){var t,e,n,r,o,i,c;function u(){(e=document.createElement("div")).classList.add("searchbox"),e.style.position="absolute",e.style.top="10px",e.style.right="10px",e.style.zIndex=10,e.innerHTML='\n\t\t',(n=e.querySelector(".searchinput")).style.width="240px",n.style.fontSize="14px",n.style.padding="4px 6px",n.style.color="#000",n.style.background="#fff",n.style.borderRadius="2px",n.style.border="0",n.style.outline="0",n.style.boxShadow="0 2px 18px rgba(0, 0, 0, 0.2)",n.style["-webkit-appearance"]="none",t.getRevealElement().appendChild(e),n.addEventListener("keyup",(function(e){switch(e.keyCode){case 13:e.preventDefault(),function(){if(i){var e=n.value;""===e?(c&&c.remove(),r=null):(c=new f("slidecontent"),r=c.apply(e),o=0)}r&&(r.length&&r.length<=o&&(o=0),r.length>o&&(t.slide(r[o].h,r[o].v),o++))}(),i=!1;break;default:i=!0}}),!1),l()}function a(){e||u(),e.style.display="inline",n.focus(),n.select()}function l(){e||u(),e.style.display="none",c&&c.remove()}function f(e,n){var r=document.getElementById(e)||document.body,o=n||"EM",i=new RegExp("^(?:"+o+"|SCRIPT|FORM)$"),c=["#ff6","#a0ffff","#9f9","#f99","#f6f"],u=[],a=0,l="",f=[];this.setRegex=function(t){t=t.replace(/^[^\w]+|[^\w]+$/g,"").replace(/[^\w'-]+/g,"|"),l=new RegExp("("+t+")","i")},this.getRegex=function(){return l.toString().replace(/^\/\\b\(|\)\\b\/i$/g,"").replace(/\|/g," ")},this.hiliteWords=function(e){if(null!=e&&e&&l&&!i.test(e.nodeName)){if(e.hasChildNodes())for(var n=0;n0?ye:he)(e)},be=Math.min,xe=function(e){return e>0?be(ve(e),9007199254740991):0},me=Math.max,Ee=Math.min,Se=function(e){return function(t,n,r){var o,i=ge(t),c=xe(i.length),u=function(e,t){var n=ve(e);return n<0?me(n+t,0):Ee(n,t)}(r,c);if(e&&n!=n){for(;c>u;)if((o=i[u++])!=o)return!0}else for(;c>u;u++)if((e||u in i)&&i[u]===n)return e||u||0;return!e&&-1}},we={includes:Se(!0),indexOf:Se(!1)}.indexOf,Re=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"].concat("length","prototype"),Oe={f:Object.getOwnPropertyNames||function(e){return function(e,t){var n,r=ge(e),o=0,i=[];for(n in r)!E(z,n)&&E(r,n)&&i.push(n);for(;t.length>o;)E(r,n=t[o++])&&(~we(i,n)||i.push(n));return i}(e,Re)}},Te=I("match"),_e=function(){var e=f(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.dotAll&&(t+="s"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t};function je(e,t){return RegExp(e,t)}var Pe={UNSUPPORTED_Y:o((function(){var e=je("a","y");return e.lastIndex=2,null!=e.exec("abcd")})),BROKEN_CARET:o((function(){var e=je("^r","gy");return e.lastIndex=2,null!=e.exec("str")}))},Ie=r,Ce=function(e){return"function"==typeof e?e:void 0},Ne=function(e,t){return arguments.length<2?Ce(Ie[e])||Ce(r[e]):Ie[e]&&Ie[e][t]||r[e]&&r[e][t]},Ae=I("species"),ke=d.f,$e=Oe.f,Le=X.set,Me=I("match"),Ue=r.RegExp,De=Ue.prototype,Fe=/a/g,Ke=/a/g,ze=new Ue(Fe)!==Fe,Be=Pe.UNSUPPORTED_Y;if(i&&le("RegExp",!ze||Be||o((function(){return Ke[Me]=!1,Ue(Fe)!=Fe||Ue(Ke)==Ke||"/a/i"!=Ue(Fe,"i")})))){for(var We=function(e,t){var n,r,o,i=this instanceof We,u=c(n=e)&&(void 0!==(r=n[Te])?!!r:"RegExp"==Q(n)),a=void 0===t;if(!i&&u&&e.constructor===We&&a)return e;ze?u&&!a&&(e=e.source):e instanceof We&&(a&&(t=_e.call(e)),e=e.source),Be&&(o=!!t&&t.indexOf("y")>-1)&&(t=t.replace(/y/g,""));var l,f,s,p,d,g=(l=ze?new Ue(e,t):Ue(e,t),f=i?this:De,s=We,fe&&"function"==typeof(p=f.constructor)&&p!==s&&c(d=p.prototype)&&d!==s.prototype&&fe(l,d),l);return Be&&o&&Le(g,{sticky:o}),g},qe=function(e){e in We||ke(We,e,{configurable:!0,get:function(){return Ue[e]},set:function(t){Ue[e]=t}})},Ge=$e(Ue),Ve=0;Ge.length>Ve;)qe(Ge[Ve++]);De.constructor=We,We.prototype=De,H(r,"RegExp",We)}!function(e){var t=Ne(e),n=d.f;i&&t&&!t[Ae]&&n(t,Ae,{configurable:!0,get:function(){return this}})}("RegExp");var Ye={}.propertyIsEnumerable,Xe=Object.getOwnPropertyDescriptor,He={f:Xe&&!Ye.call({1:2},1)?function(e){var t=Xe(this,e);return!!t&&t.enumerable}:Ye},Je=Object.getOwnPropertyDescriptor,Qe={f:i?Je:function(e,t){if(e=ge(e),t=s(t,!0),l)try{return Je(e,t)}catch(e){}if(E(e,t))return g(!He.f.call(e,t),e[t])}},Ze={f:Object.getOwnPropertySymbols},et=Ne("Reflect","ownKeys")||function(e){var t=Oe.f(f(e)),n=Ze.f;return n?t.concat(n(e)):t},tt=function(e,t){for(var n=et(t),r=d.f,o=Qe.f,i=0;i0&&(!i.multiline||i.multiline&&"\n"!==e[i.lastIndex-1])&&(a="(?: "+a+")",f=" "+f,l++),n=new RegExp("^(?:"+a+")",u)),at&&(n=new RegExp("^"+a+"$(?!\\s)",u)),ct&&(t=i.lastIndex),r=rt.call(c?n:i,f),c?r?(r.input=r.input.slice(l),r[0]=r[0].slice(l),r.index=i.lastIndex,i.lastIndex+=r[0].length):i.lastIndex=0:ct&&r&&(i.lastIndex=i.global?r.index+r[0].length:t),at&&r&&r.length>1&&ot.call(r[0],n,(function(){for(o=1;o")})),vt="$0"==="a".replace(/./,"$0"),bt=I("replace"),xt=!!/./[bt]&&""===/./[bt]("a","$0"),mt=!o((function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2!==n.length||"a"!==n[0]||"b"!==n[1]})),Et=function(e){return function(t,n){var r,o,i=String(de(t)),c=ve(n),u=i.length;return c<0||c>=u?e?"":void 0:(r=i.charCodeAt(c))<55296||r>56319||c+1===u||(o=i.charCodeAt(c+1))<56320||o>57343?e?i.charAt(c):r:e?i.slice(c,c+2):o-56320+(r-55296<<10)+65536}},St={codeAt:Et(!1),charAt:Et(!0)}.charAt,wt=function(e,t,n){return t+(n?St(e,t).length:1)},Rt=function(e,t){var n=e.exec;if("function"==typeof n){var r=n.call(e,t);if("object"!=typeof r)throw TypeError("RegExp exec method returned something other than an Object or null");return r}if("RegExp"!==Q(e))throw TypeError("RegExp#exec called on incompatible receiver");return lt.call(e,t)},Ot=Math.max,Tt=Math.min,_t=Math.floor,jt=/\$([$&'`]|\d\d?|<[^>]*>)/g,Pt=/\$([$&'`]|\d\d?)/g;!function(e,t,n,r){var i=I(e),c=!o((function(){var t={};return t[i]=function(){return 7},7!=""[e](t)})),u=c&&!o((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[ht]=function(){return n},n.flags="",n[i]=/./[i]),n.exec=function(){return t=!0,null},n[i](""),!t}));if(!c||!u||"replace"===e&&(!yt||!vt||xt)||"split"===e&&!mt){var a=/./[i],l=n(i,""[e],(function(e,t,n,r,o){return t.exec===lt?c&&!o?{done:!0,value:a.call(t,n,r)}:{done:!0,value:e.call(n,t,r)}:{done:!1}}),{REPLACE_KEEPS_$0:vt,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:xt}),f=l[0],s=l[1];H(String.prototype,e,f),H(RegExp.prototype,i,2==t?function(e,t){return s.call(e,this,t)}:function(e){return s.call(e,this)})}r&&h(RegExp.prototype[i],"sham",!0)}("replace",2,(function(e,t,n,r){var o=r.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,i=r.REPLACE_KEEPS_$0,c=o?"$":"$0";return[function(n,r){var o=de(this),i=null==n?void 0:n[e];return void 0!==i?i.call(n,o,r):t.call(String(o),n,r)},function(e,r){if(!o&&i||"string"==typeof r&&-1===r.indexOf(c)){var a=n(t,e,this,r);if(a.done)return a.value}var l=f(e),s=String(this),p="function"==typeof r;p||(r=String(r));var d=l.global;if(d){var g=l.unicode;l.lastIndex=0}for(var h=[];;){var y=Rt(l,s);if(null===y)break;if(h.push(y),!d)break;""===String(y[0])&&(l.lastIndex=wt(s,xe(l.lastIndex),g))}for(var v,b="",x=0,m=0;m=x&&(b+=s.slice(x,S)+_,x=S+E.length)}return b+s.slice(x)}];function u(e,n,r,o,i,c){var u=r+e.length,a=o.length,l=Pt;return void 0!==i&&(i=Object(de(i)),l=jt),t.call(c,l,(function(t,c){var l;switch(c.charAt(0)){case"$":return"$";case"&":return e;case"`":return n.slice(0,r);case"'":return n.slice(u);case"<":l=i[c.slice(1,-1)];break;default:var f=+c;if(0===f)return t;if(f>a){var s=_t(f/10);return 0===s?t:s<=a?void 0===o[s-1]?c.charAt(1):o[s-1]+c.charAt(1):t}l=o[f-1]}return void 0===l?"":l}))}}));return function(){var e,t,n,r,o,i,c;function u(){(t=document.createElement("div")).classList.add("searchbox"),t.style.position="absolute",t.style.top="10px",t.style.right="10px",t.style.zIndex=10,t.innerHTML='\n\t\t',(n=t.querySelector(".searchinput")).style.width="240px",n.style.fontSize="14px",n.style.padding="4px 6px",n.style.color="#000",n.style.background="#fff",n.style.borderRadius="2px",n.style.border="0",n.style.outline="0",n.style.boxShadow="0 2px 18px rgba(0, 0, 0, 0.2)",n.style["-webkit-appearance"]="none",e.getRevealElement().appendChild(t),n.addEventListener("keyup",(function(t){switch(t.keyCode){case 13:t.preventDefault(),function(){if(i){var t=n.value;""===t?(c&&c.remove(),r=null):(c=new f("slidecontent"),r=c.apply(t),o=0)}r&&(r.length&&r.length<=o&&(o=0),r.length>o&&(e.slide(r[o].h,r[o].v),o++))}(),i=!1;break;default:i=!0}}),!1),l()}function a(){t||u(),t.style.display="inline",n.focus(),n.select()}function l(){t||u(),t.style.display="none",c&&c.remove()}function f(t,n){var r=document.getElementById(t)||document.body,o=n||"EM",i=new RegExp("^(?:"+o+"|SCRIPT|FORM)$"),c=["#ff6","#a0ffff","#9f9","#f99","#f6f"],u=[],a=0,l="",f=[];this.setRegex=function(e){e=e.replace(/^[^\w]+|[^\w]+$/g,"").replace(/[^\w'-]+/g,"|"),l=new RegExp("("+e+")","i")},this.getRegex=function(){return l.toString().replace(/^\/\\b\(|\)\\b\/i$/g,"").replace(/\|/g," ")},this.hiliteWords=function(t){if(null!=t&&t&&l&&!i.test(t.nodeName)){if(t.hasChildNodes())for(var n=0;n': '>', 22 | '"': '"', 23 | "'": ''' 24 | }; 25 | 26 | const Plugin = () => { 27 | 28 | // The reveal.js instance this plugin is attached to 29 | let deck; 30 | 31 | /** 32 | * Retrieves the markdown contents of a slide section 33 | * element. Normalizes leading tabs/whitespace. 34 | */ 35 | function getMarkdownFromSlide( section ) { 36 | 37 | // look for a ' ); 45 | 46 | var leadingWs = text.match( /^\n?(\s*)/ )[1].length, 47 | leadingTabs = text.match( /^\n?(\t*)/ )[1].length; 48 | 49 | if( leadingTabs > 0 ) { 50 | text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' ); 51 | } 52 | else if( leadingWs > 1 ) { 53 | text = text.replace( new RegExp('\\n? {' + leadingWs + '}', 'g'), '\n' ); 54 | } 55 | 56 | return text; 57 | 58 | } 59 | 60 | /** 61 | * Given a markdown slide section element, this will 62 | * return all arguments that aren't related to markdown 63 | * parsing. Used to forward any other user-defined arguments 64 | * to the output markdown slide. 65 | */ 66 | function getForwardedAttributes( section ) { 67 | 68 | var attributes = section.attributes; 69 | var result = []; 70 | 71 | for( var i = 0, len = attributes.length; i < len; i++ ) { 72 | var name = attributes[i].name, 73 | value = attributes[i].value; 74 | 75 | // disregard attributes that are used for markdown loading/parsing 76 | if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue; 77 | 78 | if( value ) { 79 | result.push( name + '="' + value + '"' ); 80 | } 81 | else { 82 | result.push( name ); 83 | } 84 | } 85 | 86 | return result.join( ' ' ); 87 | 88 | } 89 | 90 | /** 91 | * Inspects the given options and fills out default 92 | * values for what's not defined. 93 | */ 94 | function getSlidifyOptions( options ) { 95 | 96 | options = options || {}; 97 | options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR; 98 | options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR; 99 | options.attributes = options.attributes || ''; 100 | 101 | return options; 102 | 103 | } 104 | 105 | /** 106 | * Helper function for constructing a markdown slide. 107 | */ 108 | function createMarkdownSlide( content, options ) { 109 | 110 | options = getSlidifyOptions( options ); 111 | 112 | var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) ); 113 | 114 | if( notesMatch.length === 2 ) { 115 | content = notesMatch[0] + ''; 116 | } 117 | 118 | // prevent script end tags in the content from interfering 119 | // with parsing 120 | content = content.replace( /<\/script>/g, SCRIPT_END_PLACEHOLDER ); 121 | 122 | return ''; 123 | 124 | } 125 | 126 | /** 127 | * Parses a data string into multiple slides based 128 | * on the passed in separator arguments. 129 | */ 130 | function slidify( markdown, options ) { 131 | 132 | options = getSlidifyOptions( options ); 133 | 134 | var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ), 135 | horizontalSeparatorRegex = new RegExp( options.separator ); 136 | 137 | var matches, 138 | lastIndex = 0, 139 | isHorizontal, 140 | wasHorizontal = true, 141 | content, 142 | sectionStack = []; 143 | 144 | // iterate until all blocks between separators are stacked up 145 | while( matches = separatorRegex.exec( markdown ) ) { 146 | var notes = null; 147 | 148 | // determine direction (horizontal by default) 149 | isHorizontal = horizontalSeparatorRegex.test( matches[0] ); 150 | 151 | if( !isHorizontal && wasHorizontal ) { 152 | // create vertical stack 153 | sectionStack.push( [] ); 154 | } 155 | 156 | // pluck slide content from markdown input 157 | content = markdown.substring( lastIndex, matches.index ); 158 | 159 | if( isHorizontal && wasHorizontal ) { 160 | // add to horizontal stack 161 | sectionStack.push( content ); 162 | } 163 | else { 164 | // add to vertical stack 165 | sectionStack[sectionStack.length-1].push( content ); 166 | } 167 | 168 | lastIndex = separatorRegex.lastIndex; 169 | wasHorizontal = isHorizontal; 170 | } 171 | 172 | // add the remaining slide 173 | ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) ); 174 | 175 | var markdownSections = ''; 176 | 177 | // flatten the hierarchical stack, and insert
tags 178 | for( var i = 0, len = sectionStack.length; i < len; i++ ) { 179 | // vertical 180 | if( sectionStack[i] instanceof Array ) { 181 | markdownSections += '
'; 182 | 183 | sectionStack[i].forEach( function( child ) { 184 | markdownSections += '
' + createMarkdownSlide( child, options ) + '
'; 185 | } ); 186 | 187 | markdownSections += '
'; 188 | } 189 | else { 190 | markdownSections += '
' + createMarkdownSlide( sectionStack[i], options ) + '
'; 191 | } 192 | } 193 | 194 | return markdownSections; 195 | 196 | } 197 | 198 | /** 199 | * Parses any current data-markdown slides, splits 200 | * multi-slide markdown into separate sections and 201 | * handles loading of external markdown. 202 | */ 203 | function processSlides( scope ) { 204 | 205 | return new Promise( function( resolve ) { 206 | 207 | var externalPromises = []; 208 | 209 | [].slice.call( scope.querySelectorAll( '[data-markdown]:not([data-markdown-parsed])') ).forEach( function( section, i ) { 210 | 211 | if( section.getAttribute( 'data-markdown' ).length ) { 212 | 213 | externalPromises.push( loadExternalMarkdown( section ).then( 214 | 215 | // Finished loading external file 216 | function( xhr, url ) { 217 | section.outerHTML = slidify( xhr.responseText, { 218 | separator: section.getAttribute( 'data-separator' ), 219 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ), 220 | notesSeparator: section.getAttribute( 'data-separator-notes' ), 221 | attributes: getForwardedAttributes( section ) 222 | }); 223 | }, 224 | 225 | // Failed to load markdown 226 | function( xhr, url ) { 227 | section.outerHTML = '
' + 228 | 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' + 229 | 'Check your browser\'s JavaScript console for more details.' + 230 | '

Remember that you need to serve the presentation HTML from a HTTP server.

' + 231 | '
'; 232 | } 233 | 234 | ) ); 235 | 236 | } 237 | else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) { 238 | 239 | section.outerHTML = slidify( getMarkdownFromSlide( section ), { 240 | separator: section.getAttribute( 'data-separator' ), 241 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ), 242 | notesSeparator: section.getAttribute( 'data-separator-notes' ), 243 | attributes: getForwardedAttributes( section ) 244 | }); 245 | 246 | } 247 | else { 248 | section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) ); 249 | } 250 | 251 | }); 252 | 253 | Promise.all( externalPromises ).then( resolve ); 254 | 255 | } ); 256 | 257 | } 258 | 259 | function loadExternalMarkdown( section ) { 260 | 261 | return new Promise( function( resolve, reject ) { 262 | 263 | var xhr = new XMLHttpRequest(), 264 | url = section.getAttribute( 'data-markdown' ); 265 | 266 | var datacharset = section.getAttribute( 'data-charset' ); 267 | 268 | // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes 269 | if( datacharset != null && datacharset != '' ) { 270 | xhr.overrideMimeType( 'text/html; charset=' + datacharset ); 271 | } 272 | 273 | xhr.onreadystatechange = function( section, xhr ) { 274 | if( xhr.readyState === 4 ) { 275 | // file protocol yields status code 0 (useful for local debug, mobile applications etc.) 276 | if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) { 277 | 278 | resolve( xhr, url ); 279 | 280 | } 281 | else { 282 | 283 | reject( xhr, url ); 284 | 285 | } 286 | } 287 | }.bind( this, section, xhr ); 288 | 289 | xhr.open( 'GET', url, true ); 290 | 291 | try { 292 | xhr.send(); 293 | } 294 | catch ( e ) { 295 | console.warn( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e ); 296 | resolve( xhr, url ); 297 | } 298 | 299 | } ); 300 | 301 | } 302 | 303 | /** 304 | * Check if a node value has the attributes pattern. 305 | * If yes, extract it and add that value as one or several attributes 306 | * to the target element. 307 | * 308 | * You need Cache Killer on Chrome to see the effect on any FOM transformation 309 | * directly on refresh (F5) 310 | * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277 311 | */ 312 | function addAttributeInElement( node, elementTarget, separator ) { 313 | 314 | var mardownClassesInElementsRegex = new RegExp( separator, 'mg' ); 315 | var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"]+?)\"|(data-[^\"= ]+?)(?=[\" ])", 'mg' ); 316 | var nodeValue = node.nodeValue; 317 | var matches, 318 | matchesClass; 319 | if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) { 320 | 321 | var classes = matches[1]; 322 | nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex ); 323 | node.nodeValue = nodeValue; 324 | while( matchesClass = mardownClassRegex.exec( classes ) ) { 325 | if( matchesClass[2] ) { 326 | elementTarget.setAttribute( matchesClass[1], matchesClass[2] ); 327 | } else { 328 | elementTarget.setAttribute( matchesClass[3], "" ); 329 | } 330 | } 331 | return true; 332 | } 333 | return false; 334 | } 335 | 336 | /** 337 | * Add attributes to the parent element of a text node, 338 | * or the element of an attribute node. 339 | */ 340 | function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) { 341 | 342 | if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) { 343 | var previousParentElement = element; 344 | for( var i = 0; i < element.childNodes.length; i++ ) { 345 | var childElement = element.childNodes[i]; 346 | if ( i > 0 ) { 347 | var j = i - 1; 348 | while ( j >= 0 ) { 349 | var aPreviousChildElement = element.childNodes[j]; 350 | if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) { 351 | previousParentElement = aPreviousChildElement; 352 | break; 353 | } 354 | j = j - 1; 355 | } 356 | } 357 | var parentSection = section; 358 | if( childElement.nodeName == "section" ) { 359 | parentSection = childElement ; 360 | previousParentElement = childElement ; 361 | } 362 | if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) { 363 | addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes ); 364 | } 365 | } 366 | } 367 | 368 | if ( element.nodeType == Node.COMMENT_NODE ) { 369 | if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) { 370 | addAttributeInElement( element, section, separatorSectionAttributes ); 371 | } 372 | } 373 | } 374 | 375 | /** 376 | * Converts any current data-markdown slides in the 377 | * DOM to HTML. 378 | */ 379 | function convertSlides() { 380 | 381 | var sections = deck.getRevealElement().querySelectorAll( '[data-markdown]:not([data-markdown-parsed])'); 382 | 383 | [].slice.call( sections ).forEach( function( section ) { 384 | 385 | section.setAttribute( 'data-markdown-parsed', true ) 386 | 387 | var notes = section.querySelector( 'aside.notes' ); 388 | var markdown = getMarkdownFromSlide( section ); 389 | 390 | section.innerHTML = marked( markdown ); 391 | addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) || 392 | section.parentNode.getAttribute( 'data-element-attributes' ) || 393 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR, 394 | section.getAttribute( 'data-attributes' ) || 395 | section.parentNode.getAttribute( 'data-attributes' ) || 396 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR); 397 | 398 | // If there were notes, we need to re-add them after 399 | // having overwritten the section's HTML 400 | if( notes ) { 401 | section.appendChild( notes ); 402 | } 403 | 404 | } ); 405 | 406 | return Promise.resolve(); 407 | 408 | } 409 | 410 | function escapeForHTML( input ) { 411 | 412 | return input.replace( /([&<>'"])/g, char => HTML_ESCAPE_MAP[char] ); 413 | 414 | } 415 | 416 | return { 417 | id: 'markdown', 418 | 419 | /** 420 | * Starts processing and converting Markdown within the 421 | * current reveal.js deck. 422 | */ 423 | init: function( reveal ) { 424 | 425 | deck = reveal; 426 | 427 | let renderer = new marked.Renderer(); 428 | 429 | renderer.code = ( code, language ) => { 430 | 431 | // Off by default 432 | let lineNumbers = ''; 433 | 434 | // Users can opt in to show line numbers and highlight 435 | // specific lines. 436 | // ```javascript [] show line numbers 437 | // ```javascript [1,4-8] highlights lines 1 and 4-8 438 | if( CODE_LINE_NUMBER_REGEX.test( language ) ) { 439 | lineNumbers = language.match( CODE_LINE_NUMBER_REGEX )[1].trim(); 440 | lineNumbers = `data-line-numbers="${lineNumbers}"`; 441 | language = language.replace( CODE_LINE_NUMBER_REGEX, '' ).trim(); 442 | } 443 | 444 | // Escape before this gets injected into the DOM to 445 | // avoid having the HTML parser alter our code before 446 | // highlight.js is able to read it 447 | code = escapeForHTML( code ); 448 | 449 | return `
${code}
`; 450 | }; 451 | 452 | marked.setOptions( { 453 | renderer, 454 | ...deck.getConfig().markdown 455 | } ); 456 | 457 | return processSlides( deck.getRevealElement() ).then( convertSlides ); 458 | 459 | }, 460 | 461 | // TODO: Do these belong in the API? 462 | processSlides: processSlides, 463 | convertSlides: convertSlides, 464 | slidify: slidify, 465 | marked: marked 466 | } 467 | 468 | }; 469 | 470 | export default Plugin; 471 | -------------------------------------------------------------------------------- /js/highlight/plugin.js: -------------------------------------------------------------------------------- 1 | import hljs from 'highlight.js' 2 | 3 | /* highlightjs-line-numbers.js 2.6.0 | (C) 2018 Yauheni Pakala | MIT License | github.com/wcoder/highlightjs-line-numbers.js */ 4 | /* Edited by Hakim for reveal.js; removed async timeout */ 5 | !function(n,e){"use strict";function t(){var n=e.createElement("style");n.type="text/css",n.innerHTML=g(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[v,L,b]),e.getElementsByTagName("head")[0].appendChild(n)}function r(t){"interactive"===e.readyState||"complete"===e.readyState?i(t):n.addEventListener("DOMContentLoaded",function(){i(t)})}function i(t){try{var r=e.querySelectorAll("code.hljs,code.nohighlight");for(var i in r)r.hasOwnProperty(i)&&l(r[i],t)}catch(o){n.console.error("LineNumbers error: ",o)}}function l(n,e){"object"==typeof n&&f(function(){n.innerHTML=s(n,e)})}function o(n,e){if("string"==typeof n){var t=document.createElement("code");return t.innerHTML=n,s(t,e)}}function s(n,e){e=e||{singleLine:!1};var t=e.singleLine?0:1;return c(n),a(n.innerHTML,t)}function a(n,e){var t=u(n);if(""===t[t.length-1].trim()&&t.pop(),t.length>e){for(var r="",i=0,l=t.length;i
{6}
',[j,m,L,b,p,i+1,t[i].length>0?t[i]:" "]);return g('{1}
',[v,r])}return n}function c(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];h(r.textContent)>0&&(r.childNodes.length>0?c(r):d(r.parentNode))}}function d(n){var e=n.className;if(/hljs-/.test(e)){for(var t=u(n.innerHTML),r=0,i="";r0?t[r]:" ";i+=g('{1}\n',[e,l])}n.innerHTML=i.trim()}}function u(n){return 0===n.length?[]:n.split(y)}function h(n){return(n.trim().match(y)||[]).length}function f(e){e()}function g(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?e[t]:n})}var v="hljs-ln",m="hljs-ln-line",p="hljs-ln-code",j="hljs-ln-numbers",L="hljs-ln-n",b="data-line-number",y=/\r\n|\r|\n/g;hljs?(hljs.initLineNumbersOnLoad=r,hljs.lineNumbersBlock=l,hljs.lineNumbersValue=o,t()):n.console.error("highlight.js not detected!")}(window,document); 6 | 7 | /*! 8 | * reveal.js plugin that adds syntax highlight support. 9 | */ 10 | 11 | const Plugin = { 12 | 13 | id: 'highlight', 14 | 15 | HIGHLIGHT_STEP_DELIMITER: '|', 16 | HIGHLIGHT_LINE_DELIMITER: ',', 17 | HIGHLIGHT_LINE_RANGE_DELIMITER: '-', 18 | 19 | hljs: hljs, 20 | 21 | /** 22 | * Highlights code blocks withing the given deck. 23 | * 24 | * Note that this can be called multiple times if 25 | * there are multiple presentations on one page. 26 | * 27 | * @param {Reveal} reveal the reveal.js instance 28 | */ 29 | init: function( reveal ) { 30 | 31 | // Read the plugin config options and provide fallbacks 32 | var config = reveal.getConfig().highlight || {}; 33 | config.highlightOnLoad = typeof config.highlightOnLoad === 'boolean' ? config.highlightOnLoad : true; 34 | config.escapeHTML = typeof config.escapeHTML === 'boolean' ? config.escapeHTML : true; 35 | 36 | [].slice.call( reveal.getRevealElement().querySelectorAll( 'pre code' ) ).forEach( function( block ) { 37 | 38 | // Code can optionally be wrapped in script template to avoid 39 | // HTML being parsed by the browser (i.e. when you need to 40 | // include <, > or & in your code). 41 | let substitute = block.querySelector( 'script[type="text/template"]' ); 42 | if( substitute ) { 43 | // textContent handles the HTML entity escapes for us 44 | block.textContent = substitute.innerHTML; 45 | } 46 | 47 | // Trim whitespace if the "data-trim" attribute is present 48 | if( block.hasAttribute( 'data-trim' ) && typeof block.innerHTML.trim === 'function' ) { 49 | block.innerHTML = betterTrim( block ); 50 | } 51 | 52 | // Escape HTML tags unless the "data-noescape" attrbute is present 53 | if( config.escapeHTML && !block.hasAttribute( 'data-noescape' )) { 54 | block.innerHTML = block.innerHTML.replace( //g, '>' ); 55 | } 56 | 57 | // Re-highlight when focus is lost (for contenteditable code) 58 | block.addEventListener( 'focusout', function( event ) { 59 | hljs.highlightBlock( event.currentTarget ); 60 | }, false ); 61 | 62 | if( config.highlightOnLoad ) { 63 | Plugin.highlightBlock( block ); 64 | } 65 | 66 | } ); 67 | 68 | // If we're printing to PDF, scroll the code highlights of 69 | // all blocks in the deck into view at once 70 | reveal.on( 'pdf-ready', function() { 71 | [].slice.call( reveal.getRevealElement().querySelectorAll( 'pre code[data-line-numbers].current-fragment' ) ).forEach( function( block ) { 72 | Plugin.scrollHighlightedLineIntoView( block, {}, true ); 73 | } ); 74 | } ); 75 | 76 | }, 77 | 78 | /** 79 | * Highlights a code block. If the node has the 80 | * 'data-line-numbers' attribute we also generate slide 81 | * numbers. 82 | * 83 | * If the block contains multiple line highlight steps, 84 | * we clone the block and create a fragment for each step. 85 | */ 86 | highlightBlock: function( block ) { 87 | 88 | hljs.highlightBlock( block ); 89 | 90 | // Don't generate line numbers for empty code blocks 91 | if( block.innerHTML.trim().length === 0 ) return; 92 | 93 | if( block.hasAttribute( 'data-line-numbers' ) ) { 94 | hljs.lineNumbersBlock( block, { singleLine: true } ); 95 | 96 | var scrollState = { currentBlock: block }; 97 | 98 | // If there is at least one highlight step, generate 99 | // fragments 100 | var highlightSteps = Plugin.deserializeHighlightSteps( block.getAttribute( 'data-line-numbers' ) ); 101 | if( highlightSteps.length > 1 ) { 102 | 103 | // If the original code block has a fragment-index, 104 | // each clone should follow in an incremental sequence 105 | var fragmentIndex = parseInt( block.getAttribute( 'data-fragment-index' ), 10 ); 106 | 107 | if( typeof fragmentIndex !== 'number' || isNaN( fragmentIndex ) ) { 108 | fragmentIndex = null; 109 | } 110 | 111 | // Generate fragments for all steps except the original block 112 | highlightSteps.slice(1).forEach( function( highlight ) { 113 | 114 | var fragmentBlock = block.cloneNode( true ); 115 | fragmentBlock.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlight ] ) ); 116 | fragmentBlock.classList.add( 'fragment' ); 117 | block.parentNode.appendChild( fragmentBlock ); 118 | Plugin.highlightLines( fragmentBlock ); 119 | 120 | if( typeof fragmentIndex === 'number' ) { 121 | fragmentBlock.setAttribute( 'data-fragment-index', fragmentIndex ); 122 | fragmentIndex += 1; 123 | } 124 | else { 125 | fragmentBlock.removeAttribute( 'data-fragment-index' ); 126 | } 127 | 128 | // Scroll highlights into view as we step through them 129 | fragmentBlock.addEventListener( 'visible', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock, scrollState ) ); 130 | fragmentBlock.addEventListener( 'hidden', Plugin.scrollHighlightedLineIntoView.bind( Plugin, fragmentBlock.previousSibling, scrollState ) ); 131 | 132 | } ); 133 | 134 | block.removeAttribute( 'data-fragment-index' ) 135 | block.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlightSteps[0] ] ) ); 136 | 137 | } 138 | 139 | // Scroll the first highlight into view when the slide 140 | // becomes visible. Note supported in IE11 since it lacks 141 | // support for Element.closest. 142 | var slide = typeof block.closest === 'function' ? block.closest( 'section:not(.stack)' ) : null; 143 | if( slide ) { 144 | var scrollFirstHighlightIntoView = function() { 145 | Plugin.scrollHighlightedLineIntoView( block, scrollState, true ); 146 | slide.removeEventListener( 'visible', scrollFirstHighlightIntoView ); 147 | } 148 | slide.addEventListener( 'visible', scrollFirstHighlightIntoView ); 149 | } 150 | 151 | Plugin.highlightLines( block ); 152 | 153 | } 154 | 155 | }, 156 | 157 | /** 158 | * Animates scrolling to the first highlighted line 159 | * in the given code block. 160 | */ 161 | scrollHighlightedLineIntoView: function( block, scrollState, skipAnimation ) { 162 | 163 | cancelAnimationFrame( scrollState.animationFrameID ); 164 | 165 | // Match the scroll position of the currently visible 166 | // code block 167 | if( scrollState.currentBlock ) { 168 | block.scrollTop = scrollState.currentBlock.scrollTop; 169 | } 170 | 171 | // Remember the current code block so that we can match 172 | // its scroll position when showing/hiding fragments 173 | scrollState.currentBlock = block; 174 | 175 | var highlightBounds = this.getHighlightedLineBounds( block ) 176 | var viewportHeight = block.offsetHeight; 177 | 178 | // Subtract padding from the viewport height 179 | var blockStyles = getComputedStyle( block ); 180 | viewportHeight -= parseInt( blockStyles.paddingTop ) + parseInt( blockStyles.paddingBottom ); 181 | 182 | // Scroll position which centers all highlights 183 | var startTop = block.scrollTop; 184 | var targetTop = highlightBounds.top + ( Math.min( highlightBounds.bottom - highlightBounds.top, viewportHeight ) - viewportHeight ) / 2; 185 | 186 | // Account for offsets in position applied to the 187 | // that holds our lines of code 188 | var lineTable = block.querySelector( '.hljs-ln' ); 189 | if( lineTable ) targetTop += lineTable.offsetTop - parseInt( blockStyles.paddingTop ); 190 | 191 | // Make sure the scroll target is within bounds 192 | targetTop = Math.max( Math.min( targetTop, block.scrollHeight - viewportHeight ), 0 ); 193 | 194 | if( skipAnimation === true || startTop === targetTop ) { 195 | block.scrollTop = targetTop; 196 | } 197 | else { 198 | 199 | // Don't attempt to scroll if there is no overflow 200 | if( block.scrollHeight <= viewportHeight ) return; 201 | 202 | var time = 0; 203 | var animate = function() { 204 | time = Math.min( time + 0.02, 1 ); 205 | 206 | // Update our eased scroll position 207 | block.scrollTop = startTop + ( targetTop - startTop ) * Plugin.easeInOutQuart( time ); 208 | 209 | // Keep animating unless we've reached the end 210 | if( time < 1 ) { 211 | scrollState.animationFrameID = requestAnimationFrame( animate ); 212 | } 213 | }; 214 | 215 | animate(); 216 | 217 | } 218 | 219 | }, 220 | 221 | /** 222 | * The easing function used when scrolling. 223 | */ 224 | easeInOutQuart: function( t ) { 225 | 226 | // easeInOutQuart 227 | return t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t; 228 | 229 | }, 230 | 231 | getHighlightedLineBounds: function( block ) { 232 | 233 | var highlightedLines = block.querySelectorAll( '.highlight-line' ); 234 | if( highlightedLines.length === 0 ) { 235 | return { top: 0, bottom: 0 }; 236 | } 237 | else { 238 | var firstHighlight = highlightedLines[0]; 239 | var lastHighlight = highlightedLines[ highlightedLines.length -1 ]; 240 | 241 | return { 242 | top: firstHighlight.offsetTop, 243 | bottom: lastHighlight.offsetTop + lastHighlight.offsetHeight 244 | } 245 | } 246 | 247 | }, 248 | 249 | /** 250 | * Visually emphasize specific lines within a code block. 251 | * This only works on blocks with line numbering turned on. 252 | * 253 | * @param {HTMLElement} block a block 254 | * @param {String} [linesToHighlight] The lines that should be 255 | * highlighted in this format: 256 | * "1" = highlights line 1 257 | * "2,5" = highlights lines 2 & 5 258 | * "2,5-7" = highlights lines 2, 5, 6 & 7 259 | */ 260 | highlightLines: function( block, linesToHighlight ) { 261 | 262 | var highlightSteps = Plugin.deserializeHighlightSteps( linesToHighlight || block.getAttribute( 'data-line-numbers' ) ); 263 | 264 | if( highlightSteps.length ) { 265 | 266 | highlightSteps[0].forEach( function( highlight ) { 267 | 268 | var elementsToHighlight = []; 269 | 270 | // Highlight a range 271 | if( typeof highlight.end === 'number' ) { 272 | elementsToHighlight = [].slice.call( block.querySelectorAll( 'table tr:nth-child(n+'+highlight.start+'):nth-child(-n+'+highlight.end+')' ) ); 273 | } 274 | // Highlight a single line 275 | else if( typeof highlight.start === 'number' ) { 276 | elementsToHighlight = [].slice.call( block.querySelectorAll( 'table tr:nth-child('+highlight.start+')' ) ); 277 | } 278 | 279 | if( elementsToHighlight.length ) { 280 | elementsToHighlight.forEach( function( lineElement ) { 281 | lineElement.classList.add( 'highlight-line' ); 282 | } ); 283 | 284 | block.classList.add( 'has-highlights' ); 285 | } 286 | 287 | } ); 288 | 289 | } 290 | 291 | }, 292 | 293 | /** 294 | * Parses and formats a user-defined string of line 295 | * numbers to highlight. 296 | * 297 | * @example 298 | * Plugin.deserializeHighlightSteps( '1,2|3,5-10' ) 299 | * // [ 300 | * // [ { start: 1 }, { start: 2 } ], 301 | * // [ { start: 3 }, { start: 5, end: 10 } ] 302 | * // ] 303 | */ 304 | deserializeHighlightSteps: function( highlightSteps ) { 305 | 306 | // Remove whitespace 307 | highlightSteps = highlightSteps.replace( /\s/g, '' ); 308 | 309 | // Divide up our line number groups 310 | highlightSteps = highlightSteps.split( Plugin.HIGHLIGHT_STEP_DELIMITER ); 311 | 312 | return highlightSteps.map( function( highlights ) { 313 | 314 | return highlights.split( Plugin.HIGHLIGHT_LINE_DELIMITER ).map( function( highlight ) { 315 | 316 | // Parse valid line numbers 317 | if( /^[\d-]+$/.test( highlight ) ) { 318 | 319 | highlight = highlight.split( Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER ); 320 | 321 | var lineStart = parseInt( highlight[0], 10 ), 322 | lineEnd = parseInt( highlight[1], 10 ); 323 | 324 | if( isNaN( lineEnd ) ) { 325 | return { 326 | start: lineStart 327 | }; 328 | } 329 | else { 330 | return { 331 | start: lineStart, 332 | end: lineEnd 333 | }; 334 | } 335 | 336 | } 337 | // If no line numbers are provided, no code will be highlighted 338 | else { 339 | 340 | return {}; 341 | 342 | } 343 | 344 | } ); 345 | 346 | } ); 347 | 348 | }, 349 | 350 | /** 351 | * Serializes parsed line number data into a string so 352 | * that we can store it in the DOM. 353 | */ 354 | serializeHighlightSteps: function( highlightSteps ) { 355 | 356 | return highlightSteps.map( function( highlights ) { 357 | 358 | return highlights.map( function( highlight ) { 359 | 360 | // Line range 361 | if( typeof highlight.end === 'number' ) { 362 | return highlight.start + Plugin.HIGHLIGHT_LINE_RANGE_DELIMITER + highlight.end; 363 | } 364 | // Single line 365 | else if( typeof highlight.start === 'number' ) { 366 | return highlight.start; 367 | } 368 | // All lines 369 | else { 370 | return ''; 371 | } 372 | 373 | } ).join( Plugin.HIGHLIGHT_LINE_DELIMITER ); 374 | 375 | } ).join( Plugin.HIGHLIGHT_STEP_DELIMITER ); 376 | 377 | } 378 | 379 | } 380 | 381 | // Function to perform a better "data-trim" on code snippets 382 | // Will slice an indentation amount on each line of the snippet (amount based on the line having the lowest indentation length) 383 | function betterTrim(snippetEl) { 384 | // Helper functions 385 | function trimLeft(val) { 386 | // Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill 387 | return val.replace(/^[\s\uFEFF\xA0]+/g, ''); 388 | } 389 | function trimLineBreaks(input) { 390 | var lines = input.split('\n'); 391 | 392 | // Trim line-breaks from the beginning 393 | for (var i = 0; i < lines.length; i++) { 394 | if (lines[i].trim() === '') { 395 | lines.splice(i--, 1); 396 | } else break; 397 | } 398 | 399 | // Trim line-breaks from the end 400 | for (var i = lines.length-1; i >= 0; i--) { 401 | if (lines[i].trim() === '') { 402 | lines.splice(i, 1); 403 | } else break; 404 | } 405 | 406 | return lines.join('\n'); 407 | } 408 | 409 | // Main function for betterTrim() 410 | return (function(snippetEl) { 411 | var content = trimLineBreaks(snippetEl.innerHTML); 412 | var lines = content.split('\n'); 413 | // Calculate the minimum amount to remove on each line start of the snippet (can be 0) 414 | var pad = lines.reduce(function(acc, line) { 415 | if (line.length > 0 && trimLeft(line).length > 0 && acc > line.length - trimLeft(line).length) { 416 | return line.length - trimLeft(line).length; 417 | } 418 | return acc; 419 | }, Number.POSITIVE_INFINITY); 420 | // Slice each line with this amount 421 | return lines.map(function(line, index) { 422 | return line.slice(pad); 423 | }) 424 | .join('\n'); 425 | })(snippetEl); 426 | } 427 | 428 | export default () => Plugin; 429 | --------------------------------------------------------------------------------