137 Commits

Author SHA1 Message Date
4f622abc34 rename leetcode-20230109.md 2023-01-10 01:34:02 +08:00
ad0267d685 fix 20230109 2023-01-10 01:29:33 +08:00
cdc0582e1d Merge branch 'leetcode-20230106' into leetcode-20230109 2023-01-10 01:26:45 +08:00
b94ff8de58 leetcode-20230106.md 2023-01-10 01:23:49 +08:00
49120378d4 增加注释和c++sort,删去最后一页 2023-01-07 22:12:27 +08:00
39604791e9 fix typo 2023-01-06 21:08:24 +08:00
5612aafda7 leetcode 20230109 2023-01-06 18:35:16 +08:00
Hakim El Hattab
4fe3946cb4 Merge pull request #3305 from lolmaus/patch-1
Gulp livereload: include subfolders to watch for changes in html and md
2022-12-07 11:27:14 +01:00
Hakim El Hattab
7fbe03946f Merge pull request #3324 from iiska/theme-dracula
Add theme 'dracula'
2022-12-07 11:24:36 +01:00
Juhamatti Niemelä
7a613a4507 Add theme 'dracula'
New theme using color palette from [Dracula](https://draculatheme.com/)
dark editor theme available for quite a number of different
applications.
2022-11-19 20:29:59 +02:00
hakimel
9f1f7789bf roll back unintended change to index content 2022-11-17 09:39:00 +01:00
Andrey Mikhaylov (lolmaus)
8492b82d12 Gulp livereload: include subfolders to watch for changes in html and md
Currently it's only watching for changes to `.html` and `.md` files located in the root of the project. I was frustrated when livereload stopped working for me: turns out it was because I put my content into subfolders.
2022-10-24 14:06:31 +03:00
hakimel
f6f657b627 4.4.0 2022-10-17 09:46:41 +02:00
hakimel
fb68f1c389 fix getAttribute exception in notes plugin #3285 2022-10-17 08:51:44 +02:00
Hakim El Hattab
468132320d remove doppler 2022-09-24 11:39:12 +02:00
hakimel
c1c4145240 fix merge error, closes #3277 2022-09-14 14:14:42 +02:00
hakimel
8a97ad58b0 prevent extra \n at end of single notes #3010 2022-09-05 11:10:32 +02:00
hakimel
01efcf2d92 merge support for multiple notes on same slide 2022-09-05 10:47:47 +02:00
hakimel
b23d15c430 fix issue were auto-animate could interfere with inherited line-height 2022-08-14 19:55:24 +02:00
hakimel
a0e48602d3 fix issue with past/future vertical slides remaining visible in Safari 15.4 (closes #3164) 2022-08-13 19:38:54 +02:00
hakimel
e219184f37 update browserlist from '> 0.5%, IE 11, not dead' to '> 2%, not dead' #2985 2022-08-08 07:58:18 +02:00
Hakim El Hattab
039972c730 tweak slides mention 2022-05-31 12:34:38 +02:00
hakimel
5a031c07b6 fix issues with overflowing fit-text when exporting to pdf #3191 #3120 2022-05-31 11:50:26 +02:00
Hakim El Hattab
a3f4caf179 Merge pull request #3191 from chivongv/fix-pdf-long-r-fit-text
fix: truncated long r-fit-text on pdf
2022-05-31 10:41:24 +02:00
Hakim El Hattab
0d5b69d551 Merge pull request #3210 from eltociear/patch-1
Fix typo in plugin.js
2022-05-20 14:32:36 +02:00
Ikko Ashimine
a8e9d8cc8a Fix typo in plugin.js
withing -> within
2022-05-19 12:42:45 +09:00
hakimel
3dade61176 notes plugin only listens for same-origin postmessages to prevent xss 2022-05-12 22:07:48 +02:00
hakimel
4b6ac46cde new attempt at speaker view xss fix 2022-05-12 14:53:40 +02:00
hakimel
0ca389721c add support for 'data-background-gradient' #2510
Co-authored-by: Giacomo Zinetti <giacomo.zinetti@giko.it>
2022-05-02 14:49:21 +02:00
hakimel
eada286ca0 fix issue where auto-animate did not work when jumping three or more slides (i.e. longer than the view distance) 2022-04-28 13:38:30 +02:00
hakimel
286d5ef561 made data-background attribute work with .webp #3200 2022-04-25 08:45:43 +02:00
Chi Vong
f319b246db fix: truncated long r-fit-text on pdf 2022-04-10 11:29:06 +02:00
Hakim El Hattab
9415ad5d7f update link 2022-04-06 13:15:08 +02:00
hakimel
1767e76cdc fix issue with #3182 when slide numbers are disabled 2022-04-04 15:33:44 +02:00
Hakim El Hattab
fca5b33530 Merge pull request #3182 from chivongv/fix-pdf-page-numbering
fix: pdf page numbering for fragment group
2022-04-04 15:25:25 +02:00
Hakim El Hattab
25ed8f2c47 Merge branch 'master' into fix-pdf-page-numbering 2022-04-04 15:25:14 +02:00
hakimel
914b2aea83 fix inconsistent fragment visibility in looping presentations #3123 2022-04-04 15:11:57 +02:00
Chi Vong
953aaad83a fix: pdf page numbering for fragment group 2022-04-02 18:59:46 +02:00
hakimel
e281b3234e always use css transforms for presentation scaling (zoom has too many quirks even if it is slightly sharper on ldpi displays) 2022-03-31 11:19:55 +02:00
hakimel
918ee5610a update lock file 2022-03-21 10:47:50 +01:00
hakimel
3fcf0db96e 4.3.1 2022-03-21 10:39:51 +01:00
hakimel
0247ae7582 notes plugin allows messsages from current/upcoming slide windows 2022-03-21 10:36:22 +01:00
hakimel
31407082eb fix #3154 2022-03-21 09:59:49 +01:00
Hakim El Hattab
db4aa0c2e7 Merge pull request #3019 from dabrahams/patch-3
Correct a comment
2022-03-21 09:41:05 +01:00
Hakim El Hattab
85fbfb26fd Merge pull request #3020 from dabrahams/patch-4
Call me crazy, but this seems like a typo
2022-03-21 09:40:31 +01:00
Hakim El Hattab
e3fb1655ad Merge pull request #3135 from dutts/patch-2
Removed incorrect possessive apostrophe
2022-03-21 09:39:27 +01:00
hakimel
bdcc2bd9dd fix vertical slide link in demo #3155 2022-03-21 09:38:31 +01:00
hakimel
f4cadb9b0e dont run full build + tests for package task #3156 2022-03-21 09:35:30 +01:00
Hakim El Hattab
d80a8d638c Merge pull request #3156 from dennybiasiolli/fix-gulp-package
gulp: fixing base path for 'package' task
2022-03-21 09:31:06 +01:00
Hakim El Hattab
57e5d102d5 Merge pull request #3157 from eric-wieser/patch-1
RevealMath.MathJax3: Allow the skipHtmlTags option to be overriden
2022-03-21 09:25:39 +01:00
Hakim El Hattab
41d5a12011 Merge pull request #3165 from CommanderRoot/rm-deprecated-substr
replace deprecated String.prototype.substr()
2022-03-21 09:23:10 +01:00
hakimel
3077ddbd09 recover support for running speaker view from file:// protocol #3158 2022-03-21 09:19:48 +01:00
Tobias Speicher
a5d1b68800 replace deprecated String.prototype.substr()
.substr() is deprecated so we replace it with .slice() which works similarily but isn't deprecated
Signed-off-by: Tobias Speicher <rootcommander@gmail.com>
2022-03-20 16:17:42 +01:00
Eric Wieser
470aa76894 Allow the skipHtmlTags option to be overriden
The previous logic here was backwards, and did not allow the user to override `options` in the mathjax config structure.
This makes it match how the `startup` and `tex` fields are merged.
2022-03-16 16:26:27 +00:00
Denny Biasiolli
1b3b83273c gulp: fixing base path for 'package' task 2022-03-16 15:51:31 +01:00
hakimel
37861335a2 add getSlidePath API method, update URL tests to work with new replaceState throttle 2022-03-09 11:10:26 +01:00
hakimel
2a239aedca debounce messages from notes -> main window, fixes #3147 2022-03-09 10:25:30 +01:00
hakimel
fc861fca50 throttle calls to replaceState to fix security error when navigating quickly in Safari #3147 2022-03-09 09:44:31 +01:00
hakimel
853764bc8c 4.3.0 2022-02-28 10:03:16 +01:00
hakimel
e325cea6b7 dependency update 2022-02-28 09:57:50 +01:00
hakimel
ffd533c40d 4.2.2 2022-02-28 09:49:40 +01:00
hakimel
c83c68500f rebuild notes plugin when html changes 2022-02-28 09:19:58 +01:00
Hakim El Hattab
c47bf217be Merge pull request #3137 from r0hanSH/fix_dom_xss
Fix DOM XSS
2022-02-28 09:17:34 +01:00
r0hanSH
32cdd3b187 Fix DOM XSS 2022-02-26 17:16:18 +05:30
hakimel
e33c3c72f9 the speaker view presentation URL can be overridden via (needed for reveal.js docs) 2022-02-25 09:42:44 +01:00
Richard D
ac46f773ee Removed incorrect possessive apostrophe 2022-02-24 12:52:52 +00:00
hakimel
5e12c6aeb7 additional cleanup when destroying #1145 2022-02-21 14:28:11 +01:00
hakimel
1e0cbe6779 reveal.js can now be uninitialized by calling Reveal.destroy() #1145 #3134 2022-02-21 13:41:36 +01:00
hakimel
ff20051861 fiv out of sync speaker view after presentation reloads #2822 #3032 2022-02-10 13:28:47 +01:00
hakimel
6b535328c0 note about changes to speaker view requiring plugin rebuild 2022-02-02 09:06:47 +01:00
Hakim El Hattab
19f04bcbcb add sponsor 2022-01-28 09:17:18 +01:00
hakimel
61055ed02b revert accidental change to demo.html 2022-01-19 18:08:08 +01:00
hakimel
f7c59649fe include sourcemaps in dist #3082 2022-01-11 13:24:24 +01:00
hakimel
dbb1d5ed19 2022 2022-01-03 12:38:51 +01:00
Hakim El Hattab
38b32c6619 update readme 2021-12-20 15:08:31 +01:00
Hakim El Hattab
66ac898b54 update readme 2021-12-20 15:02:19 +01:00
Hakim El Hattab
753a844d83 update link 2021-12-20 08:44:39 +01:00
Hakim El Hattab
1a525a7e14 update readme 2021-12-17 11:29:59 +01:00
Hakim El Hattab
9e0badff61 revamp readme, add sponsors 2021-12-17 11:18:46 +01:00
hakimel
a9277f9d46 reset transform in fullscreen mode #3080 2021-12-08 14:04:40 +01:00
hakimel
b7d65be051 fix fullscreen issues; correct size in Safari, auto-focus presentation when entering fullscreen #3080 2021-12-08 10:45:36 +01:00
Hakim El Hattab
c804611343 dark mode logo 2021-12-06 12:35:52 +01:00
hakimel
79a1674021 4.2.1 2021-12-06 12:11:39 +01:00
hakimel
9e583b8df4 fix intermittent issue with partially disappearing slides in scaled down presentations in Chrome 2021-11-24 13:30:20 +01:00
hakimel
74c0fbb6a2 fix read issue that caused double navigations fixes #3079 2021-11-24 11:30:12 +01:00
hakimel
c5d549810e refactor #3078 2021-11-24 11:07:11 +01:00
hakimel
ec32d44085 remove comment 2021-11-24 10:57:20 +01:00
Hakim El Hattab
bded1f5d39 Merge pull request #3078 from vanch3d/video
Fixing background video not playing on certain small factor devices (android)
2021-11-24 10:56:43 +01:00
Hakim El Hattab
2d050a88e2 Merge pull request #3075 from cashcat/patch1
fix npm start -- --host=0.0.0.0 unuseful
2021-11-24 10:27:02 +01:00
vanch3d
907ec735f8 rebuilt dist files (reveal.js only) 2021-11-23 09:47:32 +00:00
vanch3d
bcf83153d7 adding type to the video source tag 2021-11-23 09:42:22 +00:00
cashcat
13d0f086cc fix npm start -- --host=0.0.0.0 unuseful 2021-11-21 12:23:28 +08:00
hakimel
c79f4b5a4f fix issue with deck-wide backgroudns in pdf exports + fix #2865 2021-11-16 14:10:29 +01:00
hakimel
cc582c6ed5 update css for dart sass compatibility 2021-11-16 09:50:48 +01:00
hakimel
bed1329672 update contribution guidelines 2021-11-15 09:50:46 +01:00
hakimel
6371351d10 4.2.0 2021-11-12 12:11:10 +01:00
hakimel
2921e05554 4.2.0 2021-11-12 12:09:06 +01:00
hakimel
7f376c501a copy 2021-11-12 10:48:31 +01:00
hakimel
ceed5edc78 roll back unintended changes to default template 2021-11-11 15:13:31 +01:00
hakimel
4e8a1b3802 fix issue with internal links 2021-11-11 08:16:28 +01:00
hakimel
ad46e6293c upgrade highlight.js line number plugin, adds support for line number offsets #3050 2021-11-10 21:41:13 +01:00
hakimel
bc94d9598e roll back unintended change to build 2021-11-10 21:14:05 +01:00
hakimel
a6c0f3efac refactor hash parsing, fixes issue with autoplaying media not starting from internal links on mobile devices 2021-11-10 20:08:37 +01:00
hakimel
35b67a9f5b katex math rendering; fix broken 2477 delimiter, compatibility with external markdown #2559 2021-11-10 10:20:25 +01:00
hakimel
1ce77db3d0 tweak browser targets 2021-10-28 14:23:19 +02:00
hakimel
0ea4193001 add @burgerga's math plugin with MathJax2, MathJax3 and KaTeX support #2559 2021-10-28 13:41:57 +02:00
hakimel
810d80bc3c revert changes to md test #3027 2021-10-08 11:08:42 +02:00
hakimel
6b15e6c1ff Merge branch '3025-windows-test-fix' of https://github.com/Vandivier/reveal.js 2021-10-08 10:55:42 +02:00
hakimel
92a0d47237 syntax tweak 2021-10-08 10:30:05 +02:00
hakimel
ea14d4a08a beforeHighlight callback 2021-10-08 10:22:55 +02:00
Jens Lechtenbörger
62a85d55f8 Add generated files 2021-10-06 17:51:11 +02:00
Vandivier
7b82d12675 fix: deck 2 horizontal separator
fix for windows
line ending difference caused failure
now simple.md content mirror deck1
2021-10-05 17:01:24 -04:00
Vandivier
001129c993 chore: lock update 2021-10-05 16:49:14 -04:00
Vandivier
dda3e4b4f2 fix: host fix for windows 2021-10-05 16:48:46 -04:00
Asvin Goel
d93cba5581 var -> let 2021-10-04 12:48:42 +02:00
Asvin Goel
cc1da8aee6 Remove accidentally added tab 2021-10-04 12:19:06 +02:00
Asvin Goel
ca9ce4b592 Allow users to register additional languages via callback 2021-10-04 12:16:00 +02:00
Dave Abrahams
42d5dcab98 Call me crazy, but this seems like a typo 2021-09-28 17:38:08 -07:00
Dave Abrahams
c78e28682d Correct a comment 2021-09-28 12:33:01 -07:00
hakimel
05e57dea66 fix issue with loading base64 images #2978 2021-09-28 13:02:16 +02:00
Hakim El Hattab
0da9821e90 fix spec 2021-09-20 09:06:57 +02:00
Hakim El Hattab
cb454b0540 'slidechange' -> 'beforeslidechange' (closes #3003) 2021-09-20 09:00:17 +02:00
Jens Lechtenbörger
f9ce61e34a Support multiple aside notes elements per slide
So far, multiple notes per slide are only supported if they are
attached to fragments (without fragments, only the first aside notes
element on a slide is displayed).  With this commit, the contents of
all notes on a slide are displayed (except for fragments with notes,
for which, as before, only each fragment's first/single note is
displayed).
2021-09-16 11:56:52 +02:00
Hakim El Hattab
ad50dd513f add 'slidechange' event that can prevent navigation #3003 2021-09-16 11:15:41 +02:00
Hakim El Hattab
2aed592d1f fix last slide shortcut in looped presentations #3007 2021-09-16 10:43:40 +02:00
Hakim El Hattab
5f22d6c3da upgrade sass 2021-09-16 10:43:40 +02:00
Hakim El Hattab
6727cd6ecb fix bug that prevented first-last slide looping in linear navigation mode (closes #3009) 2021-09-16 10:43:40 +02:00
Hakim El Hattab
abe9abbed7 Merge pull request #3006 from dabrahams/patch-2
Fix copy/paste-o
2021-09-10 08:51:50 +02:00
Hakim El Hattab
dd79e7fabb Merge pull request #3005 from dabrahams/patch-1
Update comments about markdown slide separators
2021-09-10 08:51:30 +02:00
Dave Abrahams
d717c2302d Fix copy/paste-o 2021-09-09 17:22:54 -07:00
Dave Abrahams
6dd141811d Update comments about markdown slide separators
They might have been correct once upon a time, but apparently not since "---" became the default.
2021-09-09 16:49:19 -07:00
Hakim El Hattab
647c04cffe cdn video url in demo 2021-09-09 10:25:42 +02:00
Hakim El Hattab
90bbe8be4f new shortcuts; alt+arrow key skips fragments, shift+arrow key jumps to last slide in the given direction #1105 2021-09-06 13:02:58 +02:00
Hakim El Hattab
a3e8162eb1 fix unmatched h3 in test 2021-09-06 11:15:46 +02:00
Daniel Skogly
bc5ca9a452 Fix unmatched h3-tags 2021-09-06 11:14:38 +02:00
Hakim El Hattab
01d8d669bc check for slides container too #2217 2021-08-27 09:48:53 +02:00
Hakim El Hattab
e237fea99a better error message when '.reveal' root node is missing #2217 2021-08-27 09:40:33 +02:00
69 changed files with 2727 additions and 831 deletions

View File

@@ -1,10 +1,9 @@
## Contributing
Please keep the [issue tracker](http://github.com/hakimel/reveal.js/issues) limited to **bug reports**, **feature requests** and **pull requests**.
Please keep the [issue tracker](https://github.com/hakimel/reveal.js/issues) limited to **bug reports**.
### Personal Support
If you have personal support or setup questions the best place to ask those are [StackOverflow](http://stackoverflow.com/questions/tagged/reveal.js).
### General Questions and Support
If you have questions about how to use reveal.js the best place to ask is in the [Discussions](https://github.com/hakimel/reveal.js/discussions). Anything that isn't a bug report should be posted as a dicussion instead.
### Bug Reports
@@ -12,11 +11,10 @@ When reporting a bug make sure to include information about which browser and op
### Pull Requests
- Should be submitted from a feature/topic branch (not your master)
- Should follow the coding style of the file you work in, most importantly:
- Tabs to indent
- Single-quoted strings
- Should be made towards the **dev branch**
- Should be submitted from a feature/topic branch (not your master)
### Plugins

1
.gitignore vendored
View File

@@ -9,4 +9,3 @@ log/*.log
tmp/**
node_modules/
.sass-cache
dist/*.map

View File

@@ -1,4 +1,4 @@
Copyright (C) 2020 Hakim El Hattab, http://hakim.se, and reveal.js contributors
Copyright (C) 2011-2022 Hakim El Hattab, http://hakim.se, and reveal.js contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,28 +1,50 @@
<p align="center">
<a href="https://revealjs.com">
<img src="https://hakim-static.s3.amazonaws.com/reveal-js/logo/v1/reveal-black-text.svg" alt="reveal.js" width="450">
<img src="https://hakim-static.s3.amazonaws.com/reveal-js/logo/v1/reveal-black-text-sticker.png" alt="reveal.js" width="500">
</a>
<br><br>
<a href="https://github.com/hakimel/reveal.js/actions"><img src="https://github.com/hakimel/reveal.js/workflows/tests/badge.svg"></a>
<a href="https://slides.com/"><img src="https://s3.amazonaws.com/static.slid.es/images/slides-github-banner-320x40.png?1" alt="Slides" width="160" height="20"></a>
</p>
reveal.js is an open source HTML presentation framework. It enables anyone with a web browser to create fully featured and beautiful presentations for free. [Check out the live demo](https://revealjs.com/).
reveal.js is an open source HTML presentation framework. It enables anyone with a web browser to create beautiful presentations for free. Check out the live demo at [revealjs.com](https://revealjs.com/).
The framework comes with a broad range of features including [nested slides](https://revealjs.com/vertical-slides/), [Markdown support](https://revealjs.com/markdown/), [Auto-Animate](https://revealjs.com/auto-animate/), [PDF export](https://revealjs.com/pdf-export/), [speaker notes](https://revealjs.com/speaker-view/), [LaTeX support](https://revealjs.com/math/), [syntax highlighted code](https://revealjs.com/code/) and much more.
The framework comes with a powerful feature set including [nested slides](https://revealjs.com/vertical-slides/), [Markdown support](https://revealjs.com/markdown/), [Auto-Animate](https://revealjs.com/auto-animate/), [PDF export](https://revealjs.com/pdf-export/), [speaker notes](https://revealjs.com/speaker-view/), [LaTeX typesetting](https://revealjs.com/math/), [syntax highlighted code](https://revealjs.com/code/) and an [extensive API](https://revealjs.com/api/).
<h1>
<a href="https://revealjs.com/installation" style="font-size: 3em;">Get Started</a>
</h1>
---
## Documentation
The full reveal.js documentation is available at [revealjs.com](https://revealjs.com).
Want to create reveal.js presentation in a graphical editor? Try <https://slides.com>. It's made by the same people behind reveal.js.
## Online Editor
Want to create your presentation using a visual editor? Try the official reveal.js presentation platform for free at [Slides.com](https://slides.com). It's made by the same people behind reveal.js.
---
## License
### Sponsors
Hakim's open source work is supported by <a href="https://github.com/sponsors/hakimel">GitHub sponsors</a>. Special thanks to:
<div align="center">
<table>
<td align="center">
<a href="https://workos.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=revealjs&utm_source=github">
<div>
<img src="https://user-images.githubusercontent.com/629429/151508669-efb4c3b3-8fe3-45eb-8e47-e9510b5f0af1.svg" width="290" alt="WorkOS">
</div>
<b>Your app, enterprise-ready.</b>
<div>
<sub>Start selling to enterprise customers with just a few lines of code. Add Single Sign-On (and more) in minutes instead of months.</sup>
</div>
</a>
</td>
</table>
</div>
MIT licensed
---
Copyright (C) 2011-2021 Hakim El Hattab, https://hakim.se
### Getting started
- 🚀 [Install reveal.js](https://revealjs.com/installation)
- 👀 [View the demo presentation](https://revealjs.com/demo)
- 📖 [Read the documentation](https://revealjs.com/markup/)
- 🖌 [Try the visual editor for reveal.js at Slides.com](https://slides.com/)
- 🎬 [Watch the reveal.js video course (paid)](https://revealjs.com/course)
---
<div align="center">
MIT licensed | Copyright © 2011-2022 Hakim El Hattab, https://hakim.se
</div>

View File

@@ -16,7 +16,7 @@
box-sizing: border-box;
}
// Text that auto-fits it's container
// Text that auto-fits its container
.reveal .r-fit-text {
display: inline-block; // https://github.com/rikschennink/fitty#performance
white-space: nowrap;

View File

@@ -141,6 +141,11 @@
transform: none !important;
}
.reveal .r-fit-text {
white-space: normal !important;
}
.reveal section img {
display: block;
margin: 15px 0px;

View File

@@ -100,7 +100,6 @@ html.print-pdf {
box-shadow: none;
}
/* Slide backgrounds are placed inside of their slide when exporting to PDF */
.reveal .backgrounds {
display: none;

View File

@@ -1,3 +1,5 @@
@use "sass:math";
/**
* reveal.js
* http://revealjs.com
@@ -31,6 +33,16 @@ html.reveal-full-page {
color: #000;
}
// Force the presentation to cover the full viewport when we
// enter fullscreen mode. Fixes sizing issues in Safari.
.reveal-viewport:fullscreen {
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
transform: none !important;
}
/*********************************************
* VIEW FRAGMENTS
@@ -247,11 +259,11 @@ $controlsArrowAngleActive: 36deg;
@mixin controlsArrowTransform( $angle ) {
&:before {
transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( $angle );
transform: translateX(($controlArrowSize - $controlArrowLength)*0.5) translateY(($controlArrowSize - $controlArrowThickness)*0.5) rotate( $angle );
}
&:after {
transform: translateX(($controlArrowSize - $controlArrowLength)/2) translateY(($controlArrowSize - $controlArrowThickness)/2) rotate( -$angle );
transform: translateX(($controlArrowSize - $controlArrowLength)*0.5) translateY(($controlArrowSize - $controlArrowThickness)*0.5) rotate( -$angle );
}
}
@@ -300,11 +312,11 @@ $controlsArrowAngleActive: 36deg;
left: 0;
width: $controlArrowLength;
height: $controlArrowThickness;
border-radius: $controlArrowThickness/2;
border-radius: $controlArrowThickness*0.5;
background-color: currentColor;
transition: all 0.15s ease, background-color 0.8s ease;
transform-origin: floor(($controlArrowThickness/2)*10)/10 50%;
transform-origin: math.div(floor(($controlArrowThickness*0.5)*10), 10) 50%;
will-change: transform;
}
@@ -326,7 +338,7 @@ $controlsArrowAngleActive: 36deg;
.navigate-left {
right: $controlArrowSize + $controlArrowSpacing*2;
bottom: $controlArrowSpacing + $controlArrowSize/2;
bottom: $controlArrowSpacing + $controlArrowSize*0.5;
transform: translateX( -10px );
&.highlight {
@@ -336,7 +348,7 @@ $controlsArrowAngleActive: 36deg;
.navigate-right {
right: 0;
bottom: $controlArrowSpacing + $controlArrowSize/2;
bottom: $controlArrowSpacing + $controlArrowSize*0.5;
transform: translateX( 10px );
.controls-arrow {
@@ -349,7 +361,7 @@ $controlsArrowAngleActive: 36deg;
}
.navigate-up {
right: $controlArrowSpacing + $controlArrowSize/2;
right: $controlArrowSpacing + $controlArrowSize*0.5;
bottom: $controlArrowSpacing*2 + $controlArrowSize;
transform: translateY( -10px );
@@ -359,7 +371,7 @@ $controlsArrowAngleActive: 36deg;
}
.navigate-down {
right: $controlArrowSpacing + $controlArrowSize/2;
right: $controlArrowSpacing + $controlArrowSize*0.5;
bottom: -$controlArrowSpacing;
padding-bottom: $controlArrowSpacing;
transform: translateY( 10px );
@@ -515,25 +527,25 @@ $controlsArrowAngleActive: 36deg;
.navigate-left {
top: 50%;
left: $spacing;
margin-top: -$controlArrowSize/2;
margin-top: -$controlArrowSize*0.5;
}
.navigate-right {
top: 50%;
right: $spacing;
margin-top: -$controlArrowSize/2;
margin-top: -$controlArrowSize*0.5;
}
.navigate-up {
top: $spacing;
left: 50%;
margin-left: -$controlArrowSize/2;
margin-left: -$controlArrowSize*0.5;
}
.navigate-down {
bottom: $spacing - $controlArrowSpacing + 0.3em;
left: 50%;
margin-left: -$controlArrowSize/2;
margin-left: -$controlArrowSize*0.5;
}
}
@@ -711,6 +723,8 @@ $controlsArrowAngleActive: 36deg;
.reveal .slides>section.past,
.reveal .slides>section.future,
.reveal .slides>section.past>section,
.reveal .slides>section.future>section,
.reveal .slides>section>section.past,
.reveal .slides>section>section.future {
opacity: 0;
@@ -769,9 +783,6 @@ $controlsArrowAngleActive: 36deg;
*********************************************/
@each $stylename in slide, linear {
.reveal.#{$stylename} section {
backface-visibility: hidden;
}
@include transition-horizontal-past(#{$stylename}) {
transform: translate(-150%, 0);
}
@@ -1167,7 +1178,6 @@ $controlsArrowAngleActive: 36deg;
.reveal[data-background-transition=slide]>.backgrounds .slide-background:not([data-background-transition]),
.reveal>.backgrounds .slide-background[data-background-transition=slide] {
opacity: 1;
backface-visibility: hidden;
}
.reveal[data-background-transition=slide]>.backgrounds .slide-background.past:not([data-background-transition]),
.reveal>.backgrounds .slide-background.past[data-background-transition=slide] {
@@ -1701,7 +1711,7 @@ $notesWidthPercent: 25%;
.reveal .speaker-notes {
display: none;
position: absolute;
width: $notesWidthPercent / (1-$notesWidthPercent/100) * 1%;
width: math.div($notesWidthPercent, (1 - math.div($notesWidthPercent,100))) * 1%;
height: 100%;
top: 0;
left: 100%;
@@ -1764,7 +1774,6 @@ $notesWidthPercent: 25%;
top: 100%;
left: 0;
width: 100%;
height: (30/0.7)*1%;
height: 30vh;
border: 0;
}
@@ -1778,7 +1787,6 @@ $notesWidthPercent: 25%;
.reveal.show-notes .speaker-notes {
top: 100%;
height: (40/0.6)*1%;
height: 40vh;
}

View File

@@ -0,0 +1,132 @@
/**
* Dracula Dark theme for reveal.js.
* Based on https://draculatheme.com
*/
// Default mixins and settings -----------------
@import "../template/mixins";
@import "../template/settings";
// ---------------------------------------------
// Include theme-specific fonts
$systemFontsSansSerif: -apple-system,
BlinkMacSystemFont,
avenir next,
avenir,
segoe ui,
helvetica neue,
helvetica,
Cantarell,
Ubuntu,
roboto,
noto,
arial,
sans-serif;
$systemFontsMono: Menlo,
Consolas,
Monaco,
Liberation Mono,
Lucida Console,
monospace;
/**
* Dracula colors by Zeno Rocha
* https://draculatheme.com/contribute
*/
html * {
color-profile: sRGB;
rendering-intent: auto;
}
$background: #282A36;
$foreground: #F8F8F2;
$selection: #44475A;
$comment: #6272A4;
$red: #FF5555;
$orange: #FFB86C;
$yellow: #F1FA8C;
$green: #50FA7B;
$purple: #BD93F9;
$cyan: #8BE9FD;
$pink: #FF79C6;
// Override theme settings (see ../template/settings.scss)
$mainColor: $foreground;
$headingColor: $purple;
$headingTextShadow: none;
$headingTextTransform: none;
$backgroundColor: $background;
$linkColor: $pink;
$linkColorHover: $cyan;
$selectionBackgroundColor: $selection;
$inlineCodeColor: $green;
$listBulletColor: $cyan;
$mainFont: $systemFontsSansSerif;
$codeFont: "Fira Code", $systemFontsMono;
// Change text colors against light slide backgrounds
@include light-bg-text-color($background);
// Theme template ------------------------------
@import "../template/theme";
// ---------------------------------------------
// Define additional color effects based on Dracula spec
// https://spec.draculatheme.com/
:root {
--r-bold-color: #{$orange};
--r-italic-color: #{$yellow};
--r-inline-code-color: #{$inlineCodeColor};
--r-list-bullet-color: #{$listBulletColor};
}
.reveal strong, .reveal b {
color: var(--r-bold-color);
}
.reveal em, .reveal i, .reveal blockquote {
color: var(--r-italic-color);
}
.reveal code {
color: var(--r-inline-code-color);
}
// Dracula colored list bullets and numbers
.reveal ul {
list-style: none;
}
.reveal ul li::before {
content: "";
color: var(--r-list-bullet-color);
display: inline-block;
width: 1em;
margin-left: -1em
}
.reveal ol {
list-style: none;
counter-reset: li;
}
.reveal ol li::before {
content: counter(li) ".";
color: var(--r-list-bullet-color);
display: inline-block;
width: 2em;
margin-left: -2.5em;
margin-right: 0.5em;
text-align: right;
}
.reveal ol li {
counter-increment: li
}

View File

@@ -52,7 +52,7 @@
<p>Slides can be nested inside of each other.</p>
<p>Use the <em>Space</em> key to navigate through all slides.</p>
<br>
<a href="#" class="navigate-down">
<a href="#/2/1" class="navigate-down">
<img class="r-frame" style="background: rgba(255,255,255,0.1);" width="178" height="238" data-src="https://static.slid.es/reveal/arrow.png" alt="Down arrow">
</a>
</section>
@@ -273,6 +273,11 @@
<img class="r-frame" style="background: rgba(255,255,255,0.1);" width="178" height="238" data-src="https://static.slid.es/reveal/arrow.png" alt="Down arrow">
</a>
</section>
<section data-background-gradient="linear-gradient(to bottom, #283b95, #17b2c3)">
<h2>Gradient Backgrounds</h2>
<pre><code class="hljs html wrap">&lt;section data-background-gradient=
"linear-gradient(to bottom, #ddd, #191919)"&gt;</code></pre>
</section>
<section data-background="https://static.slid.es/reveal/image-placeholder.png">
<h2>Image Backgrounds</h2>
<pre><code class="hljs html">&lt;section data-background="image.png"&gt;</code></pre>
@@ -281,7 +286,7 @@
<h2>Tiled Backgrounds</h2>
<pre><code class="hljs html" style="word-wrap: break-word;">&lt;section data-background="image.png" data-background-repeat="repeat" data-background-size="100px"&gt;</code></pre>
</section>
<section data-background-video="https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4" data-background-color="#000000">
<section data-background-video="https://static.slid.es/site/homepage/v1/homepage-video-editor.mp4" data-background-color="#000000">
<div style="background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px;">
<h2>Video Backgrounds</h2>
<pre><code class="hljs html" style="word-wrap: break-word;">&lt;section data-background-video="video.mp4,video.webm"&gt;</code></pre>

6
dist/reveal.css vendored

File diff suppressed because one or more lines are too long

6
dist/reveal.esm.js vendored

File diff suppressed because one or more lines are too long

1
dist/reveal.esm.js.map vendored Normal file

File diff suppressed because one or more lines are too long

6
dist/reveal.js vendored

File diff suppressed because one or more lines are too long

1
dist/reveal.js.map vendored Normal file

File diff suppressed because one or more lines are too long

414
dist/theme/dracula.css vendored Normal file
View File

@@ -0,0 +1,414 @@
@charset "UTF-8";
/**
* Dracula Dark theme for reveal.js.
* Based on https://draculatheme.com
*/
/**
* Dracula colors by Zeno Rocha
* https://draculatheme.com/contribute
*/
html * {
color-profile: sRGB;
rendering-intent: auto;
}
section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 {
color: #282A36;
}
/*********************************************
* GLOBAL STYLES
*********************************************/
:root {
--r-background-color: #282A36;
--r-main-font: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
--r-main-font-size: 40px;
--r-main-color: #F8F8F2;
--r-block-margin: 20px;
--r-heading-margin: 0 0 20px 0;
--r-heading-font: League Gothic, Impact, sans-serif;
--r-heading-color: #BD93F9;
--r-heading-line-height: 1.2;
--r-heading-letter-spacing: normal;
--r-heading-text-transform: none;
--r-heading-text-shadow: none;
--r-heading-font-weight: normal;
--r-heading1-text-shadow: none;
--r-heading1-size: 3.77em;
--r-heading2-size: 2.11em;
--r-heading3-size: 1.55em;
--r-heading4-size: 1em;
--r-code-font: Fira Code, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
--r-link-color: #FF79C6;
--r-link-color-dark: #ff2da5;
--r-link-color-hover: #8BE9FD;
--r-selection-background-color: #44475A;
--r-selection-color: #fff;
}
.reveal-viewport {
background: #282A36;
background-color: var(--r-background-color);
}
.reveal {
font-family: var(--r-main-font);
font-size: var(--r-main-font-size);
font-weight: normal;
color: var(--r-main-color);
}
.reveal ::selection {
color: var(--r-selection-color);
background: var(--r-selection-background-color);
text-shadow: none;
}
.reveal ::-moz-selection {
color: var(--r-selection-color);
background: var(--r-selection-background-color);
text-shadow: none;
}
.reveal .slides section,
.reveal .slides section > section {
line-height: 1.3;
font-weight: inherit;
}
/*********************************************
* HEADERS
*********************************************/
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5,
.reveal h6 {
margin: var(--r-heading-margin);
color: var(--r-heading-color);
font-family: var(--r-heading-font);
font-weight: var(--r-heading-font-weight);
line-height: var(--r-heading-line-height);
letter-spacing: var(--r-heading-letter-spacing);
text-transform: var(--r-heading-text-transform);
text-shadow: var(--r-heading-text-shadow);
word-wrap: break-word;
}
.reveal h1 {
font-size: var(--r-heading1-size);
}
.reveal h2 {
font-size: var(--r-heading2-size);
}
.reveal h3 {
font-size: var(--r-heading3-size);
}
.reveal h4 {
font-size: var(--r-heading4-size);
}
.reveal h1 {
text-shadow: var(--r-heading1-text-shadow);
}
/*********************************************
* OTHER
*********************************************/
.reveal p {
margin: var(--r-block-margin) 0;
line-height: 1.3;
}
/* Remove trailing margins after titles */
.reveal h1:last-child,
.reveal h2:last-child,
.reveal h3:last-child,
.reveal h4:last-child,
.reveal h5:last-child,
.reveal h6:last-child {
margin-bottom: 0;
}
/* Ensure certain elements are never larger than the slide itself */
.reveal img,
.reveal video,
.reveal iframe {
max-width: 95%;
max-height: 95%;
}
.reveal strong,
.reveal b {
font-weight: bold;
}
.reveal em {
font-style: italic;
}
.reveal ol,
.reveal dl,
.reveal ul {
display: inline-block;
text-align: left;
margin: 0 0 0 1em;
}
.reveal ol {
list-style-type: decimal;
}
.reveal ul {
list-style-type: disc;
}
.reveal ul ul {
list-style-type: square;
}
.reveal ul ul ul {
list-style-type: circle;
}
.reveal ul ul,
.reveal ul ol,
.reveal ol ol,
.reveal ol ul {
display: block;
margin-left: 40px;
}
.reveal dt {
font-weight: bold;
}
.reveal dd {
margin-left: 40px;
}
.reveal blockquote {
display: block;
position: relative;
width: 70%;
margin: var(--r-block-margin) auto;
padding: 5px;
font-style: italic;
background: rgba(255, 255, 255, 0.05);
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2);
}
.reveal blockquote p:first-child,
.reveal blockquote p:last-child {
display: inline-block;
}
.reveal q {
font-style: italic;
}
.reveal pre {
display: block;
position: relative;
width: 90%;
margin: var(--r-block-margin) auto;
text-align: left;
font-size: 0.55em;
font-family: var(--r-code-font);
line-height: 1.2em;
word-wrap: break-word;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15);
}
.reveal code {
font-family: var(--r-code-font);
text-transform: none;
tab-size: 2;
}
.reveal pre code {
display: block;
padding: 5px;
overflow: auto;
max-height: 400px;
word-wrap: normal;
}
.reveal .code-wrapper {
white-space: normal;
}
.reveal .code-wrapper code {
white-space: pre;
}
.reveal table {
margin: auto;
border-collapse: collapse;
border-spacing: 0;
}
.reveal table th {
font-weight: bold;
}
.reveal table th,
.reveal table td {
text-align: left;
padding: 0.2em 0.5em 0.2em 0.5em;
border-bottom: 1px solid;
}
.reveal table th[align=center],
.reveal table td[align=center] {
text-align: center;
}
.reveal table th[align=right],
.reveal table td[align=right] {
text-align: right;
}
.reveal table tbody tr:last-child th,
.reveal table tbody tr:last-child td {
border-bottom: none;
}
.reveal sup {
vertical-align: super;
font-size: smaller;
}
.reveal sub {
vertical-align: sub;
font-size: smaller;
}
.reveal small {
display: inline-block;
font-size: 0.6em;
line-height: 1.2em;
vertical-align: top;
}
.reveal small * {
vertical-align: top;
}
.reveal img {
margin: var(--r-block-margin) 0;
}
/*********************************************
* LINKS
*********************************************/
.reveal a {
color: var(--r-link-color);
text-decoration: none;
transition: color 0.15s ease;
}
.reveal a:hover {
color: var(--r-link-color-hover);
text-shadow: none;
border: none;
}
.reveal .roll span:after {
color: #fff;
background: var(--r-link-color-dark);
}
/*********************************************
* Frame helper
*********************************************/
.reveal .r-frame {
border: 4px solid var(--r-main-color);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
}
.reveal a .r-frame {
transition: all 0.15s linear;
}
.reveal a:hover .r-frame {
border-color: var(--r-link-color);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
}
/*********************************************
* NAVIGATION CONTROLS
*********************************************/
.reveal .controls {
color: var(--r-link-color);
}
/*********************************************
* PROGRESS BAR
*********************************************/
.reveal .progress {
background: rgba(0, 0, 0, 0.2);
color: var(--r-link-color);
}
/*********************************************
* PRINT BACKGROUND
*********************************************/
@media print {
.backgrounds {
background-color: var(--r-background-color);
}
}
:root {
--r-bold-color: #FFB86C;
--r-italic-color: #F1FA8C;
--r-inline-code-color: #50FA7B;
--r-list-bullet-color: #8BE9FD;
}
.reveal strong, .reveal b {
color: var(--r-bold-color);
}
.reveal em, .reveal i, .reveal blockquote {
color: var(--r-italic-color);
}
.reveal code {
color: var(--r-inline-code-color);
}
.reveal ul {
list-style: none;
}
.reveal ul li::before {
content: "•";
color: var(--r-list-bullet-color);
display: inline-block;
width: 1em;
margin-left: -1em;
}
.reveal ol {
list-style: none;
counter-reset: li;
}
.reveal ol li::before {
content: counter(li) ".";
color: var(--r-list-bullet-color);
display: inline-block;
width: 2em;
margin-left: -2.5em;
margin-right: 0.5em;
text-align: right;
}
.reveal ol li {
counter-increment: li;
}

View File

@@ -125,7 +125,7 @@
</section>
<section data-auto-animate style="height: 600px">
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 1</h2>
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 1</h3>
<h2 data-id="title" style="margin-top: 260px;">Animate Anything</h2>
<div data-id="1" style="background: white; position: absolute; top: 150px; left: 16%; width: 60px; height: 60px;"></div>
<div data-id="2" style="background: white; position: absolute; top: 150px; left: 36%; width: 60px; height: 60px;"></div>
@@ -133,7 +133,7 @@
<div data-id="4" style="background: white; position: absolute; top: 150px; left: 76%; width: 60px; height: 60px;"></div>
</section>
<section data-auto-animate style="height: 600px">
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 2</h2>
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 2</h3>
<h2 data-id="title" style="margin-top: 500px">With Auto Animate</h2>
<div data-id="1" style="background: cyan; position: absolute; bottom: 190px; left: 16%; width: 60px; height: 60px;"></div>
<div data-id="2" style="background: magenta; position: absolute; bottom: 190px; left: 36%; width: 60px; height: 160px;"></div>
@@ -141,7 +141,7 @@
<div data-id="4" style="background: red; position: absolute; bottom: 190px; left: 76%; width: 60px; height: 360px;"></div>
</section>
<section data-auto-animate style="height: 600px">
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 3</h2>
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 3</h3>
<h2 data-id="title" style="margin-top: 500px; opacity: 0;">With Auto Animate</h2>
<div data-id="1" style="background: cyan; position: absolute; top: 50%; left: 50%; width: 400px; height: 400px; margin: -200px 0 0 -200px; border-radius: 400px;"></div>
<div data-id="2" style="background: magenta; position: absolute; top: 50%; left: 50%; width: 300px; height: 300px; margin: -150px 0 0 -150px; border-radius: 400px;"></div>
@@ -149,7 +149,7 @@
<div data-id="4" style="background: red; position: absolute; top: 50%; left: 50%; width: 100px; height: 100px; margin: -50px 0 0 -50px; border-radius: 400px;"></div>
</section>
<section data-auto-animate style="height: 600px">
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 3</h2>
<h3 style="opacity: 0.3; font-size: 18px;">SLIDE 3</h3>
<h2 data-id="title" style="margin-top: 500px; opacity: 0;">With Auto Animate</h2>
<div data-id="1" style="background: red; position: absolute; top: 250px; left: 16%; width: 60px; height: 60px;"></div>
<div data-id="2" style="background: yellow; position: absolute; top: 250px; left: 36%; width: 60px; height: 60px;"></div>
@@ -176,6 +176,37 @@
<h3>B2</h3>
</section>
<section>
<section id="stacked-slide-1" data-auto-animate>
<a href="#/stacked-slide-1">Slide 1</a><br>
<a href="#/stacked-slide-2">Slide 2</a><br>
<a href="#/stacked-slide-3">Slide 3</a><br>
<a href="#/stacked-slide-4">Slide 4</a><br>
<div data-id="anim" style="background: indigo; padding: 8px; width: 50px; height: 50px; position: absolute; left: 0px;">A</div>
</section>
<section id="stacked-slide-2" data-auto-animate>
<a href="#/stacked-slide-1">Slide 1</a><br>
<a href="#/stacked-slide-2">Slide 2</a><br>
<a href="#/stacked-slide-3">Slide 3</a><br>
<a href="#/stacked-slide-4">Slide 4</a><br>
<div data-id="anim" style="background: indigo; padding: 8px; width: 50px; height: 50px; position: absolute; left: 25%;">A</div>
</section>
<section id="stacked-slide-3" data-auto-animate>
<a href="#/stacked-slide-1">Slide 1</a><br>
<a href="#/stacked-slide-2">Slide 2</a><br>
<a href="#/stacked-slide-3">Slide 3</a><br>
<a href="#/stacked-slide-4">Slide 4</a><br>
<div data-id="anim" style="background: indigo; padding: 8px; width: 50px; height: 50px; position: absolute; left: 50%;">A</div>
</section>
<section id="stacked-slide-4" data-auto-animate>
<a href="#/stacked-slide-1">Slide 1</a><br>
<a href="#/stacked-slide-2">Slide 2</a><br>
<a href="#/stacked-slide-3">Slide 3</a><br>
<a href="#/stacked-slide-4">Slide 4</a><br>
<div data-id="anim" style="background: indigo; padding: 8px; width: 50px; height: 50px; position: absolute; left: 75%;">A</div>
</section>
</section>
</div>
</div>

View File

@@ -123,7 +123,7 @@
<section id="vstack">
<h2>VStack</h2>
<p>Stacks multiple elements horizontally.</p>
<p>Stacks multiple elements vertically.</p>
<pre><code class="html" data-trim data-line-numbers>
<div class="r-vstack">
&lt;img width="450" height="300" src="..."&gt;

View File

@@ -21,8 +21,8 @@
<!-- Use external markdown resource, separate slides by three newlines; vertical slides by two newlines -->
<section data-markdown="markdown.md" data-separator="^\n\n\n" data-separator-vertical="^\n\n"></section>
<!-- Slides are separated by three dashes (quick 'n dirty regular expression) -->
<section data-markdown data-separator="---">
<!-- Slides are separated by three dashes (the default) -->
<section data-markdown>
<script type="text/template">
## Demo 1
Slide 1
@@ -35,7 +35,7 @@
</script>
</section>
<!-- Slides are separated by newline + three dashes + newline, vertical slides identical but two dashes -->
<!-- Slides are separated by regexp matching newline + three dashes + newline, vertical slides identical but two dashes -->
<section data-markdown data-separator="^\n---\n$" data-separator-vertical="^\n--\n$">
<script type="text/template">
## Demo 2
@@ -53,8 +53,8 @@
</script>
</section>
<!-- No "extra" slides, since there are no separators defined (so they'll become horizontal rulers) -->
<section data-markdown>
<!-- No "extra" slides, since the separator can't be matched ("---" will become horizontal rulers) -->
<section data-markdown data-separator="$x">
<script type="text/template">
A
@@ -106,6 +106,16 @@
</script>
</section>
<!-- Math -->
<section data-markdown>
## The Lorenz Equations
`\[\begin{aligned}
\dot{x} &amp; = \sigma(y-x) \\
\dot{y} &amp; = \rho x - y - xz \\
\dot{z} &amp; = -\beta z + xy
\end{aligned} \]`
</section>
</div>
</div>
@@ -113,6 +123,7 @@
<script src="../plugin/markdown/markdown.js"></script>
<script src="../plugin/highlight/highlight.js"></script>
<script src="../plugin/notes/notes.js"></script>
<script src="../plugin/math/math.js"></script>
<script>
@@ -122,7 +133,7 @@
history: true,
center: true,
plugins: [ RevealMarkdown, RevealHighlight, RevealNotes ]
plugins: [ RevealMarkdown, RevealHighlight, RevealNotes, RevealMath.KaTeX ]
});
</script>

View File

@@ -31,6 +31,11 @@ Content 3.1
Content 3.2
## External 3.3
## External 3.3 (Image)
![External Image](https://s3.amazonaws.com/static.slid.es/logo/v2/slides-symbol-512x512.png)
## External 3.4 (Math)
`\[ J(\theta_0,\theta_1) = \sum_{i=0} \]`

View File

@@ -20,7 +20,7 @@
<section>
<h2>reveal.js Math Plugin</h2>
<p>A thin wrapper for MathJax</p>
<p>Render math with KaTeX, MathJax 2 or MathJax 3</p>
</section>
<section>
@@ -182,8 +182,7 @@
history: true,
transition: 'linear',
math: {
// mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',
mathjax2: {
config: 'TeX-AMS_HTML-full',
TeX: {
Macros: {
@@ -193,7 +192,13 @@
}
},
plugins: [ RevealMath ]
// There are three typesetters available
// RevealMath.MathJax2 (default)
// RevealMath.MathJax3
// RevealMath.KaTeX
//
// More info at https://revealjs.com/math/
plugins: [ RevealMath.MathJax2 ]
});
</script>

View File

@@ -24,13 +24,14 @@ const autoprefixer = require('gulp-autoprefixer')
const root = yargs.argv.root || '.'
const port = yargs.argv.port || 8000
const host = yargs.argv.host || 'localhost'
const banner = `/*!
* reveal.js ${pkg.version}
* ${pkg.homepage}
* MIT licensed
*
* Copyright (C) 2020 Hakim El Hattab, https://hakim.se
* Copyright (C) 2011-2022 Hakim El Hattab, https://hakim.se
*/\n`
// Prevents warnings from opening too many test pages
@@ -60,11 +61,11 @@ const babelConfig = {
// polyfilling older browsers and a larger bundle.
const babelConfigESM = JSON.parse( JSON.stringify( babelConfig ) );
babelConfigESM.presets[0][1].targets = { browsers: [
'last 2 Chrome versions', 'not Chrome < 60',
'last 2 Safari versions', 'not Safari < 10.1',
'last 2 iOS versions', 'not iOS < 10.3',
'last 2 Firefox versions', 'not Firefox < 60',
'last 2 Edge versions', 'not Edge < 16',
'last 2 Chrome versions',
'last 2 Safari versions',
'last 2 iOS versions',
'last 2 Firefox versions',
'last 2 Edge versions',
] };
let cache = {};
@@ -196,7 +197,7 @@ gulp.task('qunit', () => {
let serverConfig = {
root,
port: 8009,
host: '0.0.0.0',
host: 'localhost',
name: 'test-server'
}
@@ -268,20 +269,24 @@ gulp.task('default', gulp.series(gulp.parallel('js', 'css', 'plugins'), 'test'))
gulp.task('build', gulp.parallel('js', 'css', 'plugins'))
gulp.task('package', gulp.series('default', () =>
gulp.task('package', gulp.series(() =>
gulp.src([
'./index.html',
'./dist/**',
'./lib/**',
'./images/**',
'./plugin/**',
'./**.md'
]).pipe(zip('reveal-js-presentation.zip')).pipe(gulp.dest('./'))
gulp.src(
[
'./index.html',
'./dist/**',
'./lib/**',
'./images/**',
'./plugin/**',
'./**/*.md'
],
{ base: './' }
)
.pipe(zip('reveal-js-presentation.zip')).pipe(gulp.dest('./'))
))
gulp.task('reload', () => gulp.src(['*.html', '*.md'])
gulp.task('reload', () => gulp.src(['**/*.html', '**/*.md'])
.pipe(connect.reload()));
gulp.task('serve', () => {
@@ -289,15 +294,15 @@ gulp.task('serve', () => {
connect.server({
root: root,
port: port,
host: '0.0.0.0',
host: host,
livereload: true
})
gulp.watch(['*.html', '*.md'], gulp.series('reload'))
gulp.watch(['**/*.html', '**/*.md'], gulp.series('reload'))
gulp.watch(['js/**'], gulp.series('js', 'reload', 'test'))
gulp.watch(['js/**'], gulp.series('js', 'reload', 'eslint'))
gulp.watch(['plugin/**/plugin.js'], gulp.series('plugins', 'reload'))
gulp.watch(['plugin/**/plugin.js', 'plugin/**/*.html'], gulp.series('plugins', 'reload'))
gulp.watch([
'css/theme/source/*.{sass,scss}',

View File

@@ -1,40 +1,48 @@
<!doctype html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>reveal.js</title>
<title>reveal.js</title>
<link rel="stylesheet" href="dist/reset.css">
<link rel="stylesheet" href="dist/reveal.css">
<link rel="stylesheet" href="dist/theme/black.css">
<link rel="stylesheet" href="dist/reset.css" />
<link rel="stylesheet" href="dist/reveal.css" />
<link rel="stylesheet" href="dist/theme/black.css" />
<!-- Theme used for syntax highlighted code -->
<link rel="stylesheet" href="plugin/highlight/monokai.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section>Slide 1</section>
<section>Slide 2</section>
</div>
</div>
<!-- Theme used for syntax highlighted code -->
<link rel="stylesheet" href="plugin/highlight/monokai.css" />
</head>
<script src="dist/reveal.js"></script>
<script src="plugin/notes/notes.js"></script>
<script src="plugin/markdown/markdown.js"></script>
<script src="plugin/highlight/highlight.js"></script>
<script>
// More info about initialization & config:
// - https://revealjs.com/initialization/
// - https://revealjs.com/config/
Reveal.initialize({
hash: true,
<body>
<div class="reveal">
<div class="slides">
<section data-markdown="leetcode-20230106.md">
</section>
<section data-markdown="leetcode-20230109.md">
</section>
</div>
</div>
<script src="dist/reveal.js"></script>
<script src="plugin/notes/notes.js"></script>
<script src="plugin/math/math.js"></script>
<script src="plugin/markdown/markdown.js"></script>
<script src="plugin/highlight/highlight.js"></script>
<script>
// More info about initialization & config:
// - https://revealjs.com/initialization/
// - https://revealjs.com/config/
Reveal.initialize({
hash: true,
height: 1000,
width: 1000,
// Learn about plugins: https://revealjs.com/plugins/
plugins: [ RevealMarkdown, RevealHighlight, RevealNotes ]
});
</script>
</body>
// Learn about plugins: https://revealjs.com/plugins/
plugins: [RevealMarkdown, RevealHighlight, RevealNotes, RevealMath.KaTeX],
});
</script>
</body>
</html>

View File

@@ -50,11 +50,19 @@ export default class AutoAnimate {
// Flag the navigation direction, needed for fragment buildup
animationOptions.slideDirection = toSlideIndex > fromSlideIndex ? 'forward' : 'backward';
// If the from-slide is hidden because it has moved outside
// the view distance, we need to temporarily show it while
// measuring
let fromSlideIsHidden = fromSlide.style.display === 'none';
if( fromSlideIsHidden ) fromSlide.style.display = this.Reveal.getConfig().display;
// Inject our auto-animate styles for this transition
let css = this.getAutoAnimatableElements( fromSlide, toSlide ).map( elements => {
return this.autoAnimateElements( elements.from, elements.to, elements.options || {}, animationOptions, autoAnimateCounter++ );
} );
if( fromSlideIsHidden ) fromSlide.style.display = 'none';
// Animate unmatched elements, if enabled
if( toSlide.dataset.autoAnimateUnmatched !== 'false' && this.Reveal.getConfig().autoAnimateUnmatched === true ) {
@@ -391,7 +399,14 @@ export default class AutoAnimate {
value = { value: style.to, explicitValue: true };
}
else {
value = computedStyles[style.property];
// Use a unitless value for line-height so that it inherits properly
if( style.property === 'line-height' ) {
value = parseFloat( computedStyles['line-height'] ) / parseFloat( computedStyles['font-size'] );
}
if( isNaN(value) ) {
value = computedStyles[style.property];
}
}
if( value !== '' ) {
@@ -467,7 +482,6 @@ export default class AutoAnimate {
} );
pairs.forEach( pair => {
// Disable scale transformations on text nodes, we transition
// each individual text property instead
if( matches( pair.from, textNodes ) ) {

View File

@@ -122,6 +122,7 @@ export default class Backgrounds {
backgroundVideo: slide.getAttribute( 'data-background-video' ),
backgroundIframe: slide.getAttribute( 'data-background-iframe' ),
backgroundColor: slide.getAttribute( 'data-background-color' ),
backgroundGradient: slide.getAttribute( 'data-background-gradient' ),
backgroundRepeat: slide.getAttribute( 'data-background-repeat' ),
backgroundPosition: slide.getAttribute( 'data-background-position' ),
backgroundTransition: slide.getAttribute( 'data-background-transition' ),
@@ -150,7 +151,7 @@ export default class Backgrounds {
if( data.background ) {
// Auto-wrap image urls in url(...)
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) {
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp|webp)([?#\s]|$)/gi.test( data.background ) ) {
slide.setAttribute( 'data-background-image', data.background );
}
else {
@@ -161,13 +162,14 @@ export default class Backgrounds {
// Create a hash for this combination of background settings.
// This is used to determine when two slide backgrounds are
// the same.
if( data.background || data.backgroundColor || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {
if( data.background || data.backgroundColor || data.backgroundGradient || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {
element.setAttribute( 'data-background-hash', data.background +
data.backgroundSize +
data.backgroundImage +
data.backgroundVideo +
data.backgroundIframe +
data.backgroundColor +
data.backgroundGradient +
data.backgroundRepeat +
data.backgroundPosition +
data.backgroundTransition +
@@ -177,6 +179,7 @@ export default class Backgrounds {
// Additional and optional background properties
if( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize );
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
if( data.backgroundGradient ) element.style.backgroundImage = data.backgroundGradient;
if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );
if( dataPreload ) element.setAttribute( 'data-preload', '' );
@@ -394,4 +397,10 @@ export default class Backgrounds {
}
destroy() {
this.element.remove();
}
}

View File

@@ -188,6 +188,13 @@ export default class Controls {
}
}
destroy() {
this.unbind();
this.element.remove();
}
/**
* Event handlers for navigation control buttons.
*/

View File

@@ -79,6 +79,12 @@ export default class Focus {
}
destroy() {
this.Reveal.getRevealElement().classList.remove( 'focused' );
}
onRevealPointerDown( event ) {
this.focus();

View File

@@ -32,15 +32,15 @@ export default class Keyboard {
}
else {
this.shortcuts['N , SPACE'] = 'Next slide';
this.shortcuts['P'] = 'Previous slide';
this.shortcuts['P , Shift SPACE'] = 'Previous slide';
this.shortcuts['&#8592; , H'] = 'Navigate left';
this.shortcuts['&#8594; , L'] = 'Navigate right';
this.shortcuts['&#8593; , K'] = 'Navigate up';
this.shortcuts['&#8595; , J'] = 'Navigate down';
}
this.shortcuts['Home , Shift &#8592;'] = 'First slide';
this.shortcuts['End , Shift &#8594;'] = 'Last slide';
this.shortcuts['Alt + &#8592;/&#8593/&#8594;/&#8595;'] = 'Navigate without fragments';
this.shortcuts['Shift + &#8592;/&#8593/&#8594;/&#8595;'] = 'Jump to first/last slide';
this.shortcuts['B , .'] = 'Pause';
this.shortcuts['F'] = 'Fullscreen';
this.shortcuts['ESC, O'] = 'Slide overview';
@@ -182,13 +182,11 @@ export default class Keyboard {
let activeElementIsInput = document.activeElement && document.activeElement.tagName && /input|textarea/i.test( document.activeElement.tagName );
let activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);
// Whitelist specific modified + keycode combinations
let prevSlideShortcut = event.shiftKey && event.keyCode === 32;
let firstSlideShortcut = event.shiftKey && keyCode === 37;
let lastSlideShortcut = event.shiftKey && keyCode === 39;
// Whitelist certain modifiers for slide navigation shortcuts
let isNavigationKey = [32, 37, 38, 39, 40, 78, 80].indexOf( event.keyCode ) !== -1;
// Prevent all other events when a modifier is pressed
let unusedModifier = !prevSlideShortcut && !firstSlideShortcut && !lastSlideShortcut &&
let unusedModifier = !( isNavigationKey && event.shiftKey || event.altKey ) &&
( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey );
// Disregard the event if there's a focused element or a
@@ -277,52 +275,58 @@ export default class Keyboard {
// P, PAGE UP
if( keyCode === 80 || keyCode === 33 ) {
this.Reveal.prev();
this.Reveal.prev({skipFragments: event.altKey});
}
// N, PAGE DOWN
else if( keyCode === 78 || keyCode === 34 ) {
this.Reveal.next();
this.Reveal.next({skipFragments: event.altKey});
}
// H, LEFT
else if( keyCode === 72 || keyCode === 37 ) {
if( firstSlideShortcut ) {
if( event.shiftKey ) {
this.Reveal.slide( 0 );
}
else if( !this.Reveal.overview.isActive() && useLinearMode ) {
this.Reveal.prev();
this.Reveal.prev({skipFragments: event.altKey});
}
else {
this.Reveal.left();
this.Reveal.left({skipFragments: event.altKey});
}
}
// L, RIGHT
else if( keyCode === 76 || keyCode === 39 ) {
if( lastSlideShortcut ) {
this.Reveal.slide( Number.MAX_VALUE );
if( event.shiftKey ) {
this.Reveal.slide( this.Reveal.getHorizontalSlides().length - 1 );
}
else if( !this.Reveal.overview.isActive() && useLinearMode ) {
this.Reveal.next();
this.Reveal.next({skipFragments: event.altKey});
}
else {
this.Reveal.right();
this.Reveal.right({skipFragments: event.altKey});
}
}
// K, UP
else if( keyCode === 75 || keyCode === 38 ) {
if( !this.Reveal.overview.isActive() && useLinearMode ) {
this.Reveal.prev();
if( event.shiftKey ) {
this.Reveal.slide( undefined, 0 );
}
else if( !this.Reveal.overview.isActive() && useLinearMode ) {
this.Reveal.prev({skipFragments: event.altKey});
}
else {
this.Reveal.up();
this.Reveal.up({skipFragments: event.altKey});
}
}
// J, DOWN
else if( keyCode === 74 || keyCode === 40 ) {
if( !this.Reveal.overview.isActive() && useLinearMode ) {
this.Reveal.next();
if( event.shiftKey ) {
this.Reveal.slide( undefined, Number.MAX_VALUE );
}
else if( !this.Reveal.overview.isActive() && useLinearMode ) {
this.Reveal.next({skipFragments: event.altKey});
}
else {
this.Reveal.down();
this.Reveal.down({skipFragments: event.altKey});
}
}
// HOME
@@ -331,7 +335,7 @@ export default class Keyboard {
}
// END
else if( keyCode === 35 ) {
this.Reveal.slide( Number.MAX_VALUE );
this.Reveal.slide( this.Reveal.getHorizontalSlides().length - 1 );
}
// SPACE
else if( keyCode === 32 ) {
@@ -339,10 +343,10 @@ export default class Keyboard {
this.Reveal.overview.deactivate();
}
if( event.shiftKey ) {
this.Reveal.prev();
this.Reveal.prev({skipFragments: event.altKey});
}
else {
this.Reveal.next();
this.Reveal.next({skipFragments: event.altKey});
}
}
// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON

View File

@@ -3,6 +3,10 @@
*/
export default class Location {
// The minimum number of milliseconds that must pass between
// calls to history.replaceState
MAX_REPLACE_STATE_FREQUENCY = 1000
constructor( Reveal ) {
this.Reveal = Reveal;
@@ -10,6 +14,8 @@ export default class Location {
// Delays updates to the URL due to a Chrome thumbnailer bug
this.writeURLTimeout = 0;
this.replaceStateTimestamp = 0;
this.onWindowHashChange = this.onWindowHashChange.bind( this );
}
@@ -27,19 +33,18 @@ export default class Location {
}
/**
* Reads the current URL (hash) and navigates accordingly.
* Returns the slide indices for the given hash link.
*
* @param {string} [hash] the hash string that we want to
* find the indices for
*
* @returns slide indices or null
*/
readURL() {
let config = this.Reveal.getConfig();
let indices = this.Reveal.getIndices();
let currentSlide = this.Reveal.getCurrentSlide();
let hash = window.location.hash;
getIndicesFromHash( hash=window.location.hash ) {
// Attempt to parse the hash as either an index or name
let bits = hash.slice( 2 ).split( '/' ),
name = hash.replace( /#\/?/gi, '' );
let name = hash.replace( /^#\/?/, '' );
let bits = name.split( '/' );
// If the first bit is not fully numeric and there is a name we
// can assume that this is a named link
@@ -61,23 +66,12 @@ export default class Location {
}
catch ( error ) { }
// Ensure that we're not already on a slide with the same name
let isSameNameAsCurrentSlide = currentSlide ? currentSlide.getAttribute( 'id' ) === name : false;
if( element ) {
// If the slide exists and is not the current slide...
if ( !isSameNameAsCurrentSlide || typeof f !== 'undefined' ) {
// ...find the position of the named slide and navigate to it
let slideIndices = this.Reveal.getIndices( element );
this.Reveal.slide( slideIndices.h, slideIndices.v, f );
}
}
// If the slide doesn't exist, navigate to the current slide
else {
this.Reveal.slide( indices.h || 0, indices.v || 0 );
return { ...this.Reveal.getIndices( element ), f };
}
}
else {
const config = this.Reveal.getConfig();
let hashIndexBase = config.hashOneBasedIndex ? 1 : 0;
// Read the index components of the hash
@@ -92,10 +86,32 @@ export default class Location {
}
}
if( h !== indices.h || v !== indices.v || f !== undefined ) {
this.Reveal.slide( h, v, f );
return { h, v, f };
}
// The hash couldn't be parsed or no matching named link was found
return null
}
/**
* Reads the current URL (hash) and navigates accordingly.
*/
readURL() {
const currentIndices = this.Reveal.getIndices();
const newIndices = this.getIndicesFromHash();
if( newIndices ) {
if( ( newIndices.h !== currentIndices.h || newIndices.v !== currentIndices.v || newIndices.f !== undefined ) ) {
this.Reveal.slide( newIndices.h, newIndices.v, newIndices.f );
}
}
// If no new indices are available, we're trying to navigate to
// a slide hash that does not exist
else {
this.Reveal.slide( currentIndices.h || 0, currentIndices.v || 0 );
}
}
@@ -132,10 +148,10 @@ export default class Location {
else if( config.hash ) {
// If the hash is empty, don't add it to the URL
if( hash === '/' ) {
window.history.replaceState( null, null, window.location.pathname + window.location.search );
this.debouncedReplaceState( window.location.pathname + window.location.search );
}
else {
window.history.replaceState( null, null, '#' + hash );
this.debouncedReplaceState( '#' + hash );
}
}
// UPDATE: The below nuking of all hash changes breaks
@@ -153,6 +169,26 @@ export default class Location {
}
replaceState( url ) {
window.history.replaceState( null, null, url );
this.replaceStateTimestamp = Date.now();
}
debouncedReplaceState( url ) {
clearTimeout( this.replaceStateTimeout );
if( Date.now() - this.replaceStateTimestamp > this.MAX_REPLACE_STATE_FREQUENCY ) {
this.replaceState( url );
}
else {
this.replaceStateTimeout = setTimeout( () => this.replaceState( url ), this.MAX_REPLACE_STATE_FREQUENCY );
}
}
/**
* Return a hash URL that will resolve to the given slide location.
*

View File

@@ -1,5 +1,5 @@
/**
* Handles the showing and
* Handles the showing of speaker notes
*/
export default class Notes {
@@ -89,7 +89,7 @@ export default class Notes {
* Retrieves the speaker notes from a slide. Notes can be
* defined in two ways:
* 1. As a data-notes attribute on the slide <section>
* 2. As an <aside class="notes"> inside of the slide
* 2. With <aside class="notes"> elements inside the slide
*
* @param {HTMLElement} [slide=currentSlide]
* @return {(string|null)}
@@ -101,14 +101,20 @@ export default class Notes {
return slide.getAttribute( 'data-notes' );
}
// ... or using an <aside class="notes"> element
let notesElement = slide.querySelector( 'aside.notes' );
if( notesElement ) {
return notesElement.innerHTML;
// ... or using <aside class="notes"> elements
let notesElements = slide.querySelectorAll( 'aside.notes' );
if( notesElements ) {
return Array.from(notesElements).map( notesElement => notesElement.innerHTML ).join( '\n' );
}
return null;
}
destroy() {
this.element.remove();
}
}

View File

@@ -238,4 +238,17 @@ export default class Plugins {
}
destroy() {
Object.values( this.registeredPlugins ).forEach( plugin => {
if( typeof plugin.destroy === 'function' ) {
plugin.destroy();
}
} );
this.registeredPlugins = {};
this.asyncDependencies = [];
}
}

View File

@@ -75,6 +75,17 @@ export default class Pointer {
}
destroy() {
this.showCursor();
document.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );
document.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );
}
/**
* Called whenever there is mouse input at the document level
* to determine if the cursor is active or not.

View File

@@ -22,7 +22,7 @@ export default class Print {
const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR )
// Compute slide numbers now, before we start duplicating slides
const doingSlideNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber );
const injectPageNumbers = config.slideNumber && /all|print/i.test( config.showSlideNumber );
const slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );
@@ -46,14 +46,19 @@ export default class Print {
document.body.style.width = pageWidth + 'px';
document.body.style.height = pageHeight + 'px';
const viewportElement = document.querySelector( '.reveal-viewport' );
let presentationBackground;
if( viewportElement ) {
const viewportStyles = window.getComputedStyle( viewportElement );
if( viewportStyles && viewportStyles.background ) {
presentationBackground = viewportStyles.background;
}
}
// Make sure stretch elements fit on slide
await new Promise( requestAnimationFrame );
this.Reveal.layoutSlideContents( slideWidth, slideHeight );
// Re-run the slide layout so that r-fit-text is applied based on
// the printed slide size
slides.forEach( slide => this.Reveal.slideContent.layout( slide ) );
// Batch scrollHeight access to prevent layout thrashing
await new Promise( requestAnimationFrame );
@@ -61,6 +66,7 @@ export default class Print {
const pages = [];
const pageContainer = slides[0].parentNode;
let slideNumber = 1;
// Slide and slide background layout
slides.forEach( function( slide, index ) {
@@ -90,6 +96,13 @@ export default class Print {
page.className = 'pdf-page';
page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px';
// Copy the presentation-wide background to each individual
// page when printing
if( presentationBackground ) {
page.style.background = presentationBackground;
}
page.appendChild( slide );
// Position the slide inside of the page
@@ -97,6 +110,8 @@ export default class Print {
slide.style.top = top + 'px';
slide.style.width = slideWidth + 'px';
this.Reveal.slideContent.layout( slide );
if( slide.slideBackgroundElement ) {
page.insertBefore( slide.slideBackgroundElement, slide );
}
@@ -130,13 +145,12 @@ export default class Print {
}
// Inject slide numbers if `slideNumbers` are enabled
if( doingSlideNumbers ) {
const slideNumber = index + 1;
// Inject page numbers if `slideNumbers` are enabled
if( injectPageNumbers ) {
const numberElement = document.createElement( 'div' );
numberElement.classList.add( 'slide-number' );
numberElement.classList.add( 'slide-number-pdf' );
numberElement.innerHTML = slideNumber;
numberElement.innerHTML = slideNumber++;
page.appendChild( numberElement );
}
@@ -150,7 +164,7 @@ export default class Print {
let previousFragmentStep;
fragmentGroups.forEach( function( fragments ) {
fragmentGroups.forEach( function( fragments, index ) {
// Remove 'current-fragment' from the previous group
if( previousFragmentStep ) {
@@ -166,6 +180,14 @@ export default class Print {
// Create a separate page for the current fragment state
const clonedPage = page.cloneNode( true );
// Inject unique page numbers for fragments
if( injectPageNumbers ) {
const numberElement = clonedPage.querySelector( '.slide-number-pdf' );
const fragmentNumber = index + 1;
numberElement.innerHTML += '.' + fragmentNumber;
}
pages.push( clonedPage );
previousFragmentStep = fragments;
@@ -195,6 +217,9 @@ export default class Print {
pages.forEach( page => pageContainer.appendChild( page ) );
// Re-run JS-based content layout after the slide is added to page DOM
this.Reveal.slideContent.layout( this.Reveal.getSlidesElement() );
// Notify subscribers that the PDF layout is good to go
this.Reveal.dispatchEvent({ type: 'pdf-ready' });

View File

@@ -101,5 +101,10 @@ export default class Progress {
}
destroy() {
this.element.remove();
}
}

View File

@@ -1,5 +1,4 @@
import { HORIZONTAL_SLIDES_SELECTOR, VERTICAL_SLIDES_SELECTOR } from '../utils/constants.js'
import { extend, queryAll, closest } from '../utils/util.js'
import { extend, queryAll, closest, getMimeTypeFromFile } from '../utils/util.js'
import { isMobile } from '../utils/device.js'
import fitty from 'fitty';
@@ -102,9 +101,16 @@ export default class SlideContent {
// Images
if( backgroundImage ) {
backgroundContent.style.backgroundImage = backgroundImage.split( ',' ).map( background => {
return `url(${encodeURI(background.trim())})`;
}).join( ',' );
// base64
if( /^data:/.test( backgroundImage.trim() ) ) {
backgroundContent.style.backgroundImage = `url(${backgroundImage.trim()})`;
}
// URL(s)
else {
backgroundContent.style.backgroundImage = backgroundImage.split( ',' ).map( background => {
return `url(${encodeURI(background.trim())})`;
}).join( ',' );
}
}
// Videos
else if ( backgroundVideo && !this.Reveal.isSpeakerNotes() ) {
@@ -130,7 +136,13 @@ export default class SlideContent {
// Support comma separated lists of video sources
backgroundVideo.split( ',' ).forEach( source => {
video.innerHTML += '<source src="'+ source +'">';
let type = getMimeTypeFromFile( source );
if( type ) {
video.innerHTML += `<source src="${source}" type="${type}">`;
}
else {
video.innerHTML += `<source src="${source}">`;
}
} );
backgroundContent.appendChild( video );
@@ -174,15 +186,14 @@ export default class SlideContent {
}
/**
* Applies JS-dependent layout helpers for the given slide,
* if there are any.
* Applies JS-dependent layout helpers for the scope.
*/
layout( slide ) {
layout( scopeElement ) {
// Autosize text with the r-fit-text class based on the
// size of its container. This needs to happen after the
// slide is visible in order to measure the text.
Array.from( slide.querySelectorAll( '.r-fit-text' ) ).forEach( element => {
Array.from( scopeElement.querySelectorAll( '.r-fit-text' ) ).forEach( element => {
fitty( element, {
minSize: 24,
maxSize: this.Reveal.getConfig().height * 0.8,

View File

@@ -123,4 +123,10 @@ export default class SlideNumber {
}
destroy() {
this.element.remove();
}
}

View File

@@ -26,14 +26,14 @@ import {
} from './utils/constants.js'
// The reveal.js version
export const VERSION = '4.1.3';
export const VERSION = '4.4.0';
/**
* reveal.js
* https://revealjs.com
* MIT licensed
*
* Copyright (C) 2020 Hakim El Hattab, https://hakim.se
* Copyright (C) 2011-2022 Hakim El Hattab, https://hakim.se
*/
export default function( revealElement, options ) {
@@ -121,10 +121,14 @@ export default function( revealElement, options ) {
*/
function initialize( initOptions ) {
if( !revealElement ) throw 'Unable to find presentation root (<div class="reveal">).';
// Cache references to key DOM elements
dom.wrapper = revealElement;
dom.slides = revealElement.querySelector( '.slides' );
if( !dom.slides ) throw 'Unable to find slides container (<div class="slides">).';
// Compose our config object in order of increasing precedence:
// 1. Default reveal.js options
// 2. Options provided via Reveal.configure() prior to
@@ -186,6 +190,9 @@ export default function( revealElement, options ) {
// Prevent the slides from being scrolled out of view
setupScrollPrevention();
// Adds bindings for fullscreen mode
setupFullscreen();
// Resets all vertical slides so that only the first is visible
resetVerticalSlides();
@@ -372,6 +379,19 @@ export default function( revealElement, options ) {
}
/**
* After entering fullscreen we need to force a layout to
* get our presentations to scale correctly. This behavior
* is inconsistent across browsers but a force layout seems
* to normalize it.
*/
function setupFullscreen() {
document.addEventListener( 'fullscreenchange', onFullscreenChange );
document.addEventListener( 'webkitfullscreenchange', onFullscreenChange );
}
/**
* Registers a listener to postMessage events, this makes it
* possible to call all reveal.js API methods from another
@@ -385,32 +405,7 @@ export default function( revealElement, options ) {
function setupPostMessage() {
if( config.postMessage ) {
window.addEventListener( 'message', event => {
let data = event.data;
// Make sure we're dealing with JSON
if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) {
data = JSON.parse( data );
// Check if the requested method can be found
if( data.method && typeof Reveal[data.method] === 'function' ) {
if( POST_MESSAGE_METHOD_BLACKLIST.test( data.method ) === false ) {
const result = Reveal[data.method].apply( Reveal, data.args );
// Dispatch a postMessage event with the returned value from
// our method invocation for getter functions
dispatchPostMessage( 'callback', { method: data.method, result: result } );
}
else {
console.warn( 'reveal.js: "'+ data.method +'" is is blacklisted from the postMessage API' );
}
}
}
}, false );
window.addEventListener( 'message', onPostMessage, false );
}
}
@@ -525,6 +520,7 @@ export default function( revealElement, options ) {
controls.bind();
focus.bind();
dom.slides.addEventListener( 'click', onSlidesClicked, false );
dom.slides.addEventListener( 'transitionend', onTransitionEnd, false );
dom.pauseOverlay.addEventListener( 'click', resume, false );
@@ -550,11 +546,71 @@ export default function( revealElement, options ) {
window.removeEventListener( 'resize', onWindowResize, false );
dom.slides.removeEventListener( 'click', onSlidesClicked, false );
dom.slides.removeEventListener( 'transitionend', onTransitionEnd, false );
dom.pauseOverlay.removeEventListener( 'click', resume, false );
}
/**
* Uninitializes reveal.js by undoing changes made to the
* DOM and removing all event listeners.
*/
function destroy() {
removeEventListeners();
cancelAutoSlide();
disablePreviewLinks();
// Destroy controllers
notes.destroy();
focus.destroy();
plugins.destroy();
pointer.destroy();
controls.destroy();
progress.destroy();
backgrounds.destroy();
slideNumber.destroy();
// Remove event listeners
document.removeEventListener( 'fullscreenchange', onFullscreenChange );
document.removeEventListener( 'webkitfullscreenchange', onFullscreenChange );
document.removeEventListener( 'visibilitychange', onPageVisibilityChange, false );
window.removeEventListener( 'message', onPostMessage, false );
window.removeEventListener( 'load', layout, false );
// Undo DOM changes
if( dom.pauseOverlay ) dom.pauseOverlay.remove();
if( dom.statusElement ) dom.statusElement.remove();
document.documentElement.classList.remove( 'reveal-full-page' );
dom.wrapper.classList.remove( 'ready', 'center', 'has-horizontal-slides', 'has-vertical-slides' );
dom.wrapper.removeAttribute( 'data-transition-speed' );
dom.wrapper.removeAttribute( 'data-background-transition' );
dom.viewport.classList.remove( 'reveal-viewport' );
dom.viewport.style.removeProperty( '--slide-width' );
dom.viewport.style.removeProperty( '--slide-height' );
dom.slides.style.removeProperty( 'width' );
dom.slides.style.removeProperty( 'height' );
dom.slides.style.removeProperty( 'zoom' );
dom.slides.style.removeProperty( 'left' );
dom.slides.style.removeProperty( 'top' );
dom.slides.style.removeProperty( 'bottom' );
dom.slides.style.removeProperty( 'right' );
dom.slides.style.removeProperty( 'transform' );
Array.from( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( slide => {
slide.style.removeProperty( 'display' );
slide.style.removeProperty( 'top' );
slide.removeAttribute( 'hidden' );
slide.removeAttribute( 'aria-hidden' );
} );
}
/**
* Adds a listener to one of our custom reveal.js events,
* like slidechanged.
@@ -614,6 +670,8 @@ export default function( revealElement, options ) {
dispatchPostMessage( type );
}
return event;
}
/**
@@ -840,31 +898,12 @@ export default function( revealElement, options ) {
transformSlides( { layout: '' } );
}
else {
// Zoom Scaling
// Content remains crisp no matter how much we scale. Side
// effects are minor differences in text layout and iframe
// viewports changing size. A 200x200 iframe viewport in a
// 2x zoomed presentation ends up having a 400x400 viewport.
if( scale > 1 && Device.supportsZoom && window.devicePixelRatio < 2 ) {
dom.slides.style.zoom = scale;
dom.slides.style.left = '';
dom.slides.style.top = '';
dom.slides.style.bottom = '';
dom.slides.style.right = '';
transformSlides( { layout: '' } );
}
// Transform Scaling
// Content layout remains the exact same when scaled up.
// Side effect is content becoming blurred, especially with
// high scale values on ldpi screens.
else {
dom.slides.style.zoom = '';
dom.slides.style.left = '50%';
dom.slides.style.top = '50%';
dom.slides.style.bottom = 'auto';
dom.slides.style.right = 'auto';
transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
}
dom.slides.style.zoom = '';
dom.slides.style.left = '50%';
dom.slides.style.top = '50%';
dom.slides.style.bottom = 'auto';
dom.slides.style.right = 'auto';
transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
}
// Select all slides, vertical and horizontal
@@ -906,6 +945,8 @@ export default function( revealElement, options ) {
}
}
dom.viewport.style.setProperty( '--slide-scale', scale );
progress.update();
backgrounds.updateParallax();
@@ -1188,9 +1229,22 @@ export default function( revealElement, options ) {
* @param {number} [v=indexv] Vertical index of the target slide
* @param {number} [f] Index of a fragment within the
* target slide to activate
* @param {number} [o] Origin for use in multimaster environments
* @param {number} [origin] Origin for use in multimaster environments
*/
function slide( h, v, f, o ) {
function slide( h, v, f, origin ) {
// Dispatch an event before hte slide
const slidechange = dispatchEvent({
type: 'beforeslidechange',
data: {
indexh: h === undefined ? indexh : h,
indexv: v === undefined ? indexv : v,
origin
}
});
// Abort if this slide change was prevented by an event listener
if( slidechange.defaultPrevented ) return;
// Remember where we were at before
previousSlide = currentSlide;
@@ -1326,7 +1380,7 @@ export default function( revealElement, options ) {
indexv,
previousSlide,
currentSlide,
origin: o
origin
}
});
}
@@ -1517,15 +1571,20 @@ export default function( revealElement, options ) {
slidesLength = slides.length;
let printMode = print.isPrintingPDF();
let loopedForwards = false;
let loopedBackwards = false;
if( slidesLength ) {
// Should the index loop?
if( config.loop ) {
if( index >= slidesLength ) loopedForwards = true;
index %= slidesLength;
if( index < 0 ) {
index = slidesLength + index;
loopedBackwards = true;
}
}
@@ -1563,10 +1622,7 @@ export default function( revealElement, options ) {
if( config.fragments ) {
// Show all fragments in prior slides
Util.queryAll( element, '.fragment' ).forEach( fragment => {
fragment.classList.add( 'visible' );
fragment.classList.remove( 'current-fragment' );
} );
showFragmentsIn( element );
}
}
else if( i > index ) {
@@ -1575,9 +1631,17 @@ export default function( revealElement, options ) {
if( config.fragments ) {
// Hide all fragments in future slides
Util.queryAll( element, '.fragment.visible' ).forEach( fragment => {
fragment.classList.remove( 'visible', 'current-fragment' );
} );
hideFragmentsIn( element );
}
}
// Update the visibility of fragments when a presentation loops
// in either direction
else if( i === index && config.fragments ) {
if( loopedForwards ) {
hideFragmentsIn( element );
}
else if( loopedBackwards ) {
showFragmentsIn( element );
}
}
}
@@ -1617,6 +1681,29 @@ export default function( revealElement, options ) {
}
/**
* Shows all fragment elements within the given contaienr.
*/
function showFragmentsIn( container ) {
Util.queryAll( container, '.fragment' ).forEach( fragment => {
fragment.classList.add( 'visible' );
fragment.classList.remove( 'current-fragment' );
} );
}
/**
* Hides all fragment elements within the given contaienr.
*/
function hideFragmentsIn( container ) {
Util.queryAll( container, '.fragment.visible' ).forEach( fragment => {
fragment.classList.remove( 'visible', 'current-fragment' );
} );
}
/**
* Optimization method; hide all slides that are far away
* from the present slide.
@@ -2193,55 +2280,55 @@ export default function( revealElement, options ) {
}
function navigateLeft() {
function navigateLeft({skipFragments=false}={}) {
navigationHistory.hasNavigatedHorizontally = true;
// Reverse for RTL
if( config.rtl ) {
if( ( overview.isActive() || fragments.next() === false ) && availableRoutes().left ) {
if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().left ) {
slide( indexh + 1, config.navigationMode === 'grid' ? indexv : undefined );
}
}
// Normal navigation
else if( ( overview.isActive() || fragments.prev() === false ) && availableRoutes().left ) {
else if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().left ) {
slide( indexh - 1, config.navigationMode === 'grid' ? indexv : undefined );
}
}
function navigateRight() {
function navigateRight({skipFragments=false}={}) {
navigationHistory.hasNavigatedHorizontally = true;
// Reverse for RTL
if( config.rtl ) {
if( ( overview.isActive() || fragments.prev() === false ) && availableRoutes().right ) {
if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().right ) {
slide( indexh - 1, config.navigationMode === 'grid' ? indexv : undefined );
}
}
// Normal navigation
else if( ( overview.isActive() || fragments.next() === false ) && availableRoutes().right ) {
else if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().right ) {
slide( indexh + 1, config.navigationMode === 'grid' ? indexv : undefined );
}
}
function navigateUp() {
function navigateUp({skipFragments=false}={}) {
// Prioritize hiding fragments
if( ( overview.isActive() || fragments.prev() === false ) && availableRoutes().up ) {
if( ( overview.isActive() || skipFragments || fragments.prev() === false ) && availableRoutes().up ) {
slide( indexh, indexv - 1 );
}
}
function navigateDown() {
function navigateDown({skipFragments=false}={}) {
navigationHistory.hasNavigatedVertically = true;
// Prioritize revealing fragments
if( ( overview.isActive() || fragments.next() === false ) && availableRoutes().down ) {
if( ( overview.isActive() || skipFragments || fragments.next() === false ) && availableRoutes().down ) {
slide( indexh, indexv + 1 );
}
@@ -2253,12 +2340,12 @@ export default function( revealElement, options ) {
* 2) Previous vertical slide
* 3) Previous horizontal slide
*/
function navigatePrev() {
function navigatePrev({skipFragments=false}={}) {
// Prioritize revealing fragments
if( fragments.prev() === false ) {
if( skipFragments || fragments.prev() === false ) {
if( availableRoutes().up ) {
navigateUp();
navigateUp({skipFragments});
}
else {
// Fetch the previous horizontal slide, if there is one
@@ -2271,11 +2358,16 @@ export default function( revealElement, options ) {
previousSlide = Util.queryAll( dom.wrapper, HORIZONTAL_SLIDES_SELECTOR + '.past' ).pop();
}
if( previousSlide ) {
// When going backwards and arriving on a stack we start
// at the bottom of the stack
if( previousSlide && previousSlide.classList.contains( 'stack' ) ) {
let v = ( previousSlide.querySelectorAll( 'section' ).length - 1 ) || undefined;
let h = indexh - 1;
slide( h, v );
}
else {
navigateLeft({skipFragments});
}
}
}
@@ -2284,13 +2376,13 @@ export default function( revealElement, options ) {
/**
* The reverse of #navigatePrev().
*/
function navigateNext() {
function navigateNext({skipFragments=false}={}) {
navigationHistory.hasNavigatedHorizontally = true;
navigationHistory.hasNavigatedVertically = true;
// Prioritize revealing fragments
if( fragments.next() === false ) {
if( skipFragments || fragments.next() === false ) {
let routes = availableRoutes();
@@ -2302,13 +2394,13 @@ export default function( revealElement, options ) {
}
if( routes.down ) {
navigateDown();
navigateDown({skipFragments});
}
else if( config.rtl ) {
navigateLeft();
navigateLeft({skipFragments});
}
else {
navigateRight();
navigateRight({skipFragments});
}
}
@@ -2333,6 +2425,38 @@ export default function( revealElement, options ) {
}
/**
* Listener for post message events posted to this window.
*/
function onPostMessage( event ) {
let data = event.data;
// Make sure we're dealing with JSON
if( typeof data === 'string' && data.charAt( 0 ) === '{' && data.charAt( data.length - 1 ) === '}' ) {
data = JSON.parse( data );
// Check if the requested method can be found
if( data.method && typeof Reveal[data.method] === 'function' ) {
if( POST_MESSAGE_METHOD_BLACKLIST.test( data.method ) === false ) {
const result = Reveal[data.method].apply( Reveal, data.args );
// Dispatch a postMessage event with the returned value from
// our method invocation for getter functions
dispatchPostMessage( 'callback', { method: data.method, result: result } );
}
else {
console.warn( 'reveal.js: "'+ data.method +'" is is blacklisted from the postMessage API' );
}
}
}
}
/**
* Event listener for transition end on the current slide.
*
@@ -2350,6 +2474,33 @@ export default function( revealElement, options ) {
}
/**
* A global listener for all click events inside of the
* .slides container.
*
* @param {object} [event]
*/
function onSlidesClicked( event ) {
const anchor = Util.closest( event.target, 'a[href^="#"]' );
// If a hash link is clicked, we find the target slide
// and navigate to it. We previously relied on 'hashchange'
// for links like these but that prevented media with
// audio tracks from playing in mobile browsers since it
// wasn't considered a direct interaction with the document.
if( anchor ) {
const hash = anchor.getAttribute( 'href' );
const indices = location.getIndicesFromHash( hash );
if( indices ) {
Reveal.slide( indices.h, indices.v, indices.f );
event.preventDefault();
}
}
}
/**
* Handler for the window level 'resize' event.
*
@@ -2380,6 +2531,26 @@ export default function( revealElement, options ) {
}
/**
* Handler for the document level 'fullscreenchange' event.
*
* @param {object} [event]
*/
function onFullscreenChange( event ) {
let element = document.fullscreenElement || document.webkitFullscreenElement;
if( element === dom.wrapper ) {
event.stopImmediatePropagation();
// Timeout to avoid layout shift in Safari
setTimeout( () => {
Reveal.layout();
Reveal.focus.focus(); // focus.focus :'(
}, 1 );
}
}
/**
* Handles clicks on links that are set to preview in the
* iframe overlay.
@@ -2432,6 +2603,7 @@ export default function( revealElement, options ) {
initialize,
configure,
destroy,
sync,
syncSlide,
@@ -2588,6 +2760,9 @@ export default function( revealElement, options ) {
// Helper method, retrieves query string as a key:value map
getQueryHash: Util.getQueryHash,
// Returns the path to the current slide as represented in the URL
getSlidePath: location.getHash.bind( location ),
// Returns reveal.js DOM elements
getRevealElement: () => revealElement,
getSlidesElement: () => dom.slides,

View File

@@ -29,9 +29,9 @@ export const colorToRgb = ( color ) => {
if( hex6 && hex6[1] ) {
hex6 = hex6[1];
return {
r: parseInt( hex6.substr( 0, 2 ), 16 ),
g: parseInt( hex6.substr( 2, 2 ), 16 ),
b: parseInt( hex6.substr( 4, 2 ), 16 )
r: parseInt( hex6.slice( 0, 2 ), 16 ),
g: parseInt( hex6.slice( 2, 4 ), 16 ),
b: parseInt( hex6.slice( 4, 6 ), 16 )
};
}

View File

@@ -4,7 +4,7 @@ export const HORIZONTAL_SLIDES_SELECTOR = '.slides>section';
export const VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section';
// Methods that may not be invoked via the postMessage API
export const POST_MESSAGE_METHOD_BLACKLIST = /registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener/;
export const POST_MESSAGE_METHOD_BLACKLIST = /registerPlugin|registerKeyboardShortcut|addKeyBinding|addEventListener|showPreview/;
// Regex for retrieving the fragment style from a class attribute
export const FRAGMENT_STYLE_REGEX = /fade-(down|up|right|left|out|in-then-out|in-then-semi-out)|semi-fade-out|current-visible|shrink|grow/;

View File

@@ -1,5 +1,4 @@
const UA = navigator.userAgent;
const testElement = document.createElement( 'div' );
export const isMobile = /(iphone|ipod|ipad|android)/gi.test( UA ) ||
( navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1 ); // iPadOS
@@ -7,9 +6,3 @@ export const isMobile = /(iphone|ipod|ipad|android)/gi.test( UA ) ||
export const isChrome = /chrome/i.test( UA ) && !/edge/i.test( UA );
export const isAndroid = /android/gi.test( UA );
// Flags if we should use zoom instead of transform to scale
// up slides. Zoom produces crisper results but has a lot of
// xbrowser quirks so we only use it in whitelisted browsers.
export const supportsZoom = 'zoom' in testElement.style && !isMobile &&
( isChrome || /Version\/[\d\.]+.*Safari/.test( UA ) );

View File

@@ -280,3 +280,18 @@ export const getRemainingHeight = ( element, height = 0 ) => {
return height;
}
const fileExtensionToMimeMap = {
'mp4': 'video/mp4',
'm4a': 'video/mp4',
'ogv': 'video/ogg',
'mpeg': 'video/mpeg',
'webm': 'video/webm'
}
/**
* Guess the MIME type for common file formats.
*/
export const getMimeTypeFromFile = ( filename='' ) => {
return fileExtensionToMimeMap[filename.split('.').pop()]
}

154
leetcode-20230106.md Normal file
View File

@@ -0,0 +1,154 @@
### Leetcode 💻 寒假 20230106
---
### 20. Valid Parentheses
验证左右括号是否匹配 (利用Stack)
```cpp [|3-11|12-20|22-24|26|28|29-32|34-40|44|]
class Solution {
public:
// 判断左右括号是否相等
inline bool match(const char &left, const char &right) {
switch (left) {
case '(': return right == ')';
case '{': return right == '}';
case '[': return right == ']';
}
return false;
}
// 判断是不是左括号
inline bool is_left(const char &c) {
switch (c) {
case '(': return true;
case '{': return true;
case '[': return true;
}
return false;
}
bool isValid(string s) {
// 判断长度是否为偶数
if (s.length() % 2 != 0)
return false;
stack<char> myStack;
for (auto const &c : s) {
if (is_left(c)) {
myStack.push(c);
continue;
}
if (myStack.empty())
return false;
if (!match(myStack.top(), c))
return false;
myStack.pop();
}
// 如果结束之后 stack 中还有元素
return myStack.empty();
}
};
```
Note:
3-10 首先有两个辅助函数一个叫match,用来判断左右括号是否相等,
12-20 然后是另一个函数慵懒判断是不是左括号。
22-24 进入主函数,先判断一下字符串长度是基数还是偶数,
如果是基数说明里面的括号肯定是不能左右匹配的就可以直接返回false
26 然后创建一个stack类型的变量myStack
28 然后用变量c去遍历s,这里用到的是c++11的语法auto是自动推断类型
const表示c是不能被更改的and符号表示这是一个左值引用
c的类型可以简单理解为字符串中的字符
29-32 如果c是左括号那么直接往stack中添加这个c,然后直接进入下一个循环
34-40 刚刚的语句已经把做括号的情况处理掉了那么剩下的情况就是c是右括号的情况。
我们先检查stack中是否为空为空的话说明stack中没有括号可以和c互相对应
那么让函数返回false。
接著取stack中最顶的括号和c进行配对如果不匹配返回false。
最后调用stack的pop方法移除stack中最顶部的括号。
44 最后的最后所有字符都匹配完了如果stack中还残留有括号
说明这个字符串也是不匹配的
---
### 84. Largest Rectangle in Histogram
```cpp [|2-4|6-8|26-28|9-10|12-14|16-20|23|26-31|]
int largestRectangleArea(vector<int> &heights) {
int ans = 0;
// 定义 stack 储存增序长方形
stack<int> order;
// 往 stack 中添加位于 index 的高度 height 的长方形
auto append = [&ans, &order, &heights]
(int index, int value) -> void {
// 计算单个长方形面积
ans = max(ans, value);
// stack 不为空 且 需要添加的长方形矮于 stack 中的长方形
while (!order.empty() &&
value < heights[order.top()]) {
// 计算面积
int h = heights[order.top()];
order.pop();
int w = index - 1 - (order.empty() ? -1 : order.top());
ans = max(ans, h * w);
}
order.push(index);
};
for (int i = 0; i < heights.size(); i++) {
append(i, heights[i]);
}
// 处理edge case, 在最末尾添加一个高度为-1的长方形
// 这将会计算stack中所有残留的长方形的面积
append(heights.size(), -1);
return ans;
}
```
Note:
2-4 首先定义一个整数变量answer,代表这道题的计算结果,
然后定义一个stack,元素类型是整数,用来储存长方形的索引,
注意是储存的是长方形的索引不是长方形的高度。
6-8 然后由于这部分代码要在多个地方被调用所以这里我用了c++11的匿名函数
append是函数名它接受两个参数一个是index一个是value,它没有返回值所以是void。
同时这个函数可以访问并修改ans,order,height,这里的and符号是表示捕获引用变量的意思
各位理解为这个函数可以在函数内修改到函数外的变量就行了。
26-28 定义好函数之后会在一个循环中遍历题目给的这个高度列表,
然后调用函数,传入每个长方形的索引和高度
9-10 进入函数后首先计算单个长方形的面积
12-14 然后进入一个循环,
循环的条件是stack 不为空 且 需要添加的长方形矮于 stack 中的长方形
16-20 在循环内获得高度h和宽度w,注意这里先调用了pop然后在调用top,
如果stack里面是空的那么调用top会引起奇怪的错误所以一定要检查是否为空。
这里用了一个三元表达式,如果空则返回-1,否则正常返回top.
23 循环结束之后也就是需要添加的长方形比stack中的长方形都高的时候
我们可以把它添加仅stack了
26-31 这是刚刚看到调用append的代码
注意代码运行到这里stack中是还有长方形的stack中残留的长方形还没有计算面积。
所以在最末尾的位置添加一个高度为-1的长方形
由于stack中的所有长方形都是正数加个-1进去会计算stack中残留的长方形面积。

305
leetcode-20230109.md Normal file
View File

@@ -0,0 +1,305 @@
# Leetcode 💻 寒假 20230109
---
### 169. Majority Element
> The majority element is the element that appears more than [n / 2] times.
```python [3]
class Solution:
def majorityElement(self, nums: List[int]) -> int:
return sorted(nums)[(len(nums)) // 2]
```
以下操作等价
```python
print(int(5 / 2)) # 2
print(5 // 2) # 2
```
Note:
第169题找出列表中出现次数最多的元素。
题目给了一个关键信息就是这个要找的元素出现次数超过n/2,
也就是超过这个列表长度的一半。
那么最简单的写法就是对数组进行排序,然后返回他的中位数。
注意我这里写了两个除号这是python整除的意思
---
### 56. Merge Intervals
```python [|2|4|5-7|9-12|14-15]
def merge(self, intervals):
intervals.sort(key = lambda i: i[0])
ret = []
for begin, end in intervals:
if not ret:
ret.append([begin, end])
continue
# overlap
if ret[-1][1] >= begin:
ret[-1][1] = max(end, ret[-1][1])
continue
ret.append([begin, end])
return ret
```
Note:
2首先对intervals进行排序注意intervals里灭个元素都是一个列表
这里key参数我们给他传入一个lambda临时函数
这个函数是干什么的呢他的任务就是输入一个i,然后返回i的第零个元素
意思是告诉排序函数你在排序的时候要用i的第零个元素作为排序的依据
4接着我们用begin和end这两个变量遍历intervals数组
5-7我们先处理第一种特殊情况就是ret数组为空
这种情况直接把当前遍历到的begin和end添加进去就行了
9-12第二种情况是发生了overlap我们需要把ret最后一个元素的end更新为最大的end.
14-15如果上面两种特殊情况都没有发生那么我们正常把begin和end添加到列表里就行了
---
### 避免嵌套
坏👎
```python []
if gpa < 2:
return 'failed'
else:
if gpa < 3:
return "good"
else:
return "excellent"
```
好👍
```python []
if gpa < 2:
return "failed"
if gpa < 3:
return "good"
return "excellent"
```
Note:
这里有个函数根据一个整数gpa变量返回对应的字符串。
假设这里用 if 判断第一种比较接近自然语言如果gpa小于2则返回failed
不然的话接着判断如果gpa小于3则返回good,不然就返回4。
第二种方法则比较符合程序设计思想,
先从条件范围小的情况开始处理先处理gpa小于2,然后处理gpa小于3
最后一个return是精髓保证这个函数无论在什么情况下都有一个返回值。
第一种情况下很多人写着写着就忘了返回值,然后各种内存报错又找不到在哪里出错,非常痛苦
---
### 避免嵌套基本思想
```python []
if 特殊情况:
处理特殊情况()
return
if 其他特殊情况:
处理其他特殊情况()
return
做该做的事情()
```
Note:
避免嵌套的基本思想就是early return,就是说进入函数之后,
先处理特殊情况和各种边界情况处理完之后直接return这个函数也就是early return.
最后再开始做函数该做的事情一般来说这都是比较好的写法如果你去看golang代码
你能看到大量这样的写法这也是golang社区和官方建议的写法。
---
### 15. 3Sum
```python [|4-8|6]
import itertools
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
ret = {
tuple(sorted(test))
for test in itertools.combinations(nums, 3)
if sum(test) == 0
}
return list(ret)
```
### List Comprehensions
求 0 到 100 所有能被 7 整除数的平方和
```python []
sum([i ** 2 for i in range(100) if i % 7 == 0])
```
### 迭代器
标准库提供的多种高效排列组合工具
```python []
list(itertools.combinations([1,2,3,4], 3))
# [(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
```
Note:
这题的解法其实也就一行就是4-8行的这个列表生成式那么列表生成式是什么捏。
列表生成式又叫做List comprehensions, 这里有个例子假设我们要求0到100所有能被7整除数的平方和
这个计算用列表生成式一行就能实现。首先最开始是个sum函数sum函数里面是一个列表
这个列表是中的每一个元素都是i的平方那么i从哪里来的呢i是for i in range(100) 这个循环中出来的,
并且i满足i除以7的余数是0这个条件。
回到4-8行ret是一个集合集合中每个元素是 **经过排序** 的 **元组** test,
test从哪里来呢test 是 第七行 这个for循环迭代出来的变量并且这个test满足第八行的这个求和等于0的条件。
那么这个itertools.combinations是什么函数呢它是标准库中提供的排列组合迭代器。
下面给各位回忆一下高中排列组合的知识假设我们有一个列表列表中有元素1 2 3 4,每次取三个不同的元素,
那么一共有多少中不同的排列组合呢。用combinations函数就能非常方便的帮我们遍历所有排列组合。
理论上,这题就这么可以解出来了,但是实际上是不行的
```
---
但是时间复杂度 `$O(n^3)$`
3000 数组长度就是 27,000,000,000 次循环(百亿)😢
python for 循环在一般电脑上一秒钟能跑一千万次左右
思路:哈希表(字典)具有 `$O(1)$` 查找速度,使用字典代替最深的一层循环,将算法优化为 `$O(n^2)$`
```python [|5-7|9-14|16-17|18-21|22-25|27-34|36-38]
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
# 处理全是相同数字的特殊情况
if min(nums) == max(nums) and sum(nums) == 0:
return [[min(nums)] * 3]
# 生成反向字典,之后用于加速查找
reverse = {}
for key, val in enumerate(nums):
if reverse.get(val) is None:
reverse[val] = []
reverse[val].append(key)
# 创建集合,集合中元素是不可重复的
ret = set()
for index_i in range(len(nums)-2):
i = nums[index_i]
for index_j in range(index_i+1, len(nums)-1):
j = nums[index_j]
# 由于 sum((i,j,k)) == 0计算出需要的 k 是多少
k = -(i + j)
test = reverse.get(k)
# 情况1字典没有满足 sum((i,j,k))==0 的k
if test is None:
continue
# 情况2&3字典中有满足需求的k但它的索引是 i 或者 j
if len(test) == 1 and (index_i in test or index_j in test):
continue
if len(test) == 2 and (index_i in test and index_j in test):
continue
# 对 (i,j,k) 排序后放入元组中
# 利用元组不可重复的特性去掉重复结果
ret.add(tuple(sorted([i, j, k])))
return list(ret)
```
---
### 406. Queue Reconstruction by height
利用 list.insert() 能在指定位置插入元素,并把后面的元素往后移动的特点
```python [|2-3,6-8|]
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
# 按 p[0] 降序排p[0] 相同的情况下按 p[1] 升序排
people.sort(key = lambda p: (-p[0], p[1]))
res = []
for p in people:
# 在 p[1] 位置插入 p后面的元素会向后移动一位
# [TODO] 使用链表优化性能但这已经AC了能AC的就是好的👍
res.insert(p[1], p)
return res
# [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
```
⚠ python 标准库中有双向链表 `collections.deque`
⚠ c++ 标准库中也有链表 list
Note:
这道题其实也就两行代码第一行是将people排序第二行是在新数组中指定位置插入元素。
解题的关键就在利用了插入排序的特性,列表中后来插入的元素把之前插入的元素往后推一个位置。
但题外话我想提一下,
我们写算法关注算法性能,这没问题,但我自己个人是把代码简洁度看得比性能更重的。
写程序像写作一样,不光要机器能跑,还要其他人能看得懂,不光要看得懂,还要看得舒服,
怎么才算看得舒服呢,我个人认为是代码符合思维直觉,一个屏幕长度内的代码表达的信息量恰到好处,
不像流水账一样冗余,也不像汇编语言那样要盯着一行思考很久,当然我说了不算,
有本书叫《代码简洁之道》就专门讨论这类软件工程问题,感兴趣的可以找来看看。
还有就是标准库很重要,当然不是说要你把标注库背下来,
只是说要了解标准库能做到什么,还有了解你用的语言有哪些语法糖,
比如说三元表达式,不知道三元表达式这个语法糖的可以自己去查一下,
大部分现代语言比如python或者c++都有三元表达式这个语法糖,它能让代码更简短更简洁,
总的来说标准库的作用就是等你要用到相关功能的时候就知道去哪里查,而不是说自己重复造轮子
---
## C++
```cpp [|4|6-7|9-12|14-18]
#include <algorithm>
int main() {
std::array<int, 10> s = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
// 默认升序排序
std::sort(s.begin(), s.end());
// 自定义降序排序函数
std::sort(s.begin(), s.end, [](int a, int b) {
return a > b;
})
// 循环输出
for (auto const &i : s) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
```
---
### C++ 标准库中的排序以C11为例
- 快速排序平均复杂度为 `$O(N log N)$` ,最坏情况下为 `$O(N^2)$`,快排递归带来额外开销
- 堆排序比快排慢,但最坏情况下为 `$(N log N)$`
- 插入排序在大致有序的情况下表现非常好
`std::sort` 实现了 Introspective sorting集成了三种算法各自的优点
---
## End 🎉

546
package-lock.json generated
View File

@@ -1,11 +1,12 @@
{
"name": "reveal.js",
"version": "4.1.0",
"version": "4.4.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "4.1.0",
"name": "reveal.js",
"version": "4.4.0",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.14.3",
@@ -20,7 +21,7 @@
"fitty": "^2.3.0",
"glob": "^7.1.7",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^5.0.0",
"gulp-autoprefixer": "^8.0.0",
"gulp-clean-css": "^4.2.0",
"gulp-connect": "^5.7.0",
"gulp-eslint": "^6.0.0",
@@ -28,12 +29,12 @@
"gulp-tap": "^2.0.0",
"gulp-zip": "^4.2.0",
"highlight.js": "^10.0.3",
"marked": "^2.0.3",
"node-qunit-puppeteer": "^2.0.1",
"qunit": "^2.10.0",
"marked": "^4.0.12",
"node-qunit-puppeteer": "^2.1.0",
"qunit": "^2.17.2",
"rollup": "^2.48.0",
"rollup-plugin-terser": "^7.0.2",
"sass": "^1.32.13",
"sass": "^1.39.2",
"yargs": "^15.1.0"
},
"engines": {
@@ -1619,9 +1620,9 @@
}
},
"node_modules/ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
@@ -1903,33 +1904,30 @@
}
},
"node_modules/autoprefixer": {
"version": "8.6.5",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz",
"integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==",
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
"integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==",
"dev": true,
"dependencies": {
"browserslist": "^3.2.8",
"caniuse-lite": "^1.0.30000864",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001297",
"fraction.js": "^4.1.2",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
"postcss": "^6.0.23",
"postcss-value-parser": "^3.2.3"
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
},
"bin": {
"autoprefixer": "bin/autoprefixer"
}
},
"node_modules/autoprefixer/node_modules/browserslist": {
"version": "3.2.8",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
"integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
"dev": true,
"dependencies": {
"caniuse-lite": "^1.0.30000844",
"electron-to-chromium": "^1.3.47"
},
"bin": {
"browserslist": "cli.js"
"engines": {
"node": "^10 || ^12 || >=14"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/babel-plugin-dynamic-import-node": {
@@ -2111,16 +2109,16 @@
}
},
"node_modules/browserslist": {
"version": "4.16.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
"version": "4.19.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz",
"integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==",
"dev": true,
"dependencies": {
"caniuse-lite": "^1.0.30001219",
"colorette": "^1.2.2",
"electron-to-chromium": "^1.3.723",
"caniuse-lite": "^1.0.30001312",
"electron-to-chromium": "^1.4.71",
"escalade": "^3.1.1",
"node-releases": "^1.1.71"
"node-releases": "^2.0.2",
"picocolors": "^1.0.0"
},
"bin": {
"browserslist": "cli.js"
@@ -2227,14 +2225,20 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001228",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz",
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
"version": "1.0.30001374",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
"dev": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
}
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
}
]
},
"node_modules/chalk": {
"version": "2.4.2",
@@ -2538,12 +2542,6 @@
"color-support": "bin.js"
}
},
"node_modules/colorette": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
"dev": true
},
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
@@ -2554,9 +2552,9 @@
}
},
"node_modules/commander": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz",
"integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true,
"engines": {
"node": ">= 10"
@@ -2924,9 +2922,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.3.732",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.732.tgz",
"integrity": "sha512-qKD5Pbq+QMk4nea4lMuncUMhpEiQwaJyCW7MrvissnRcBDENhVfDmAqQYRQ3X525oTzhar9Zh1cK0L2d1UKYcw==",
"version": "1.4.73",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz",
"integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -3886,6 +3884,19 @@
"node": ">=0.10.0"
}
},
"node_modules/fraction.js": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz",
"integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==",
"dev": true,
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"url": "https://www.patreon.com/infusion"
}
},
"node_modules/fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -4200,20 +4211,52 @@
}
},
"node_modules/gulp-autoprefixer": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-5.0.0.tgz",
"integrity": "sha1-gjfCeKaXdScKHK/n1vEBz81YVUQ=",
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-8.0.0.tgz",
"integrity": "sha512-sVR++PIaXpa81p52dmmA/jt50bw0egmylK5mjagfgOJ8uLDGaF9tHyzvetkY9Uo0gBZUS5sVqN3kX/GlUKOyog==",
"dev": true,
"license": "MIT",
"dependencies": {
"autoprefixer": "^8.0.0",
"fancy-log": "^1.3.2",
"autoprefixer": "^10.2.6",
"fancy-log": "^1.3.3",
"plugin-error": "^1.0.1",
"postcss": "^6.0.1",
"through2": "^2.0.0",
"vinyl-sourcemaps-apply": "^0.2.0"
"postcss": "^8.3.0",
"through2": "^4.0.2",
"vinyl-sourcemaps-apply": "^0.2.1"
},
"engines": {
"node": ">=4.5"
"node": ">=12"
},
"peerDependencies": {
"gulp": ">=4"
},
"peerDependenciesMeta": {
"gulp": {
"optional": true
}
}
},
"node_modules/gulp-autoprefixer/node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dev": true,
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/gulp-autoprefixer/node_modules/through2": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
"integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
"dev": true,
"dependencies": {
"readable-stream": "3"
}
},
"node_modules/gulp-clean-css": {
@@ -5579,15 +5622,6 @@
"node": ">=8"
}
},
"node_modules/js-reporters": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-2.0.0.tgz",
"integrity": "sha512-VJd/86niT7GzsaVc+Yxrs8QPrYl1orzv8bYZPuSOtxU6rk/pv8aOXTcIa7HaANvtvdLMTsZspAiucNQ6T2QFHw==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -5911,15 +5945,15 @@
}
},
"node_modules/marked": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-2.0.3.tgz",
"integrity": "sha512-5otztIIcJfPc2qGTN8cVtOJEjNJZ0jwa46INMagrYfk0EvqtRuEHLsEe0LrFS0/q+ZRKT0+kXK7P2T1AN5lWRA==",
"version": "4.0.12",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz",
"integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==",
"dev": true,
"bin": {
"marked": "bin/marked"
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 8.16.2"
"node": ">= 12"
}
},
"node_modules/matchdep": {
@@ -6177,6 +6211,18 @@
"dev": true,
"optional": true
},
"node_modules/nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -6273,9 +6319,9 @@
"dev": true
},
"node_modules/node-qunit-puppeteer": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/node-qunit-puppeteer/-/node-qunit-puppeteer-2.0.3.tgz",
"integrity": "sha512-G4mWn3RBQ+JPzCNWzFQ4r6RUUZqj52D5E3Z7wxqRi5b4daph0Alk/mgBpAQqZq7TVR1oV2emnN0Bk0EgYz/4gw==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-qunit-puppeteer/-/node-qunit-puppeteer-2.1.0.tgz",
"integrity": "sha512-53ytjfu+t51r9qbOsek5D9biAlGO808Pp6b1gGdg/fcGJGFZIJNHoVpFF3OLRe7IUXA9QjhsQL9IkK4NGenHCA==",
"dev": true,
"dependencies": {
"colors": "^1.4.0",
@@ -6286,15 +6332,15 @@
}
},
"node_modules/node-releases": {
"version": "1.1.72",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
"integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
"integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
"dev": true
},
"node_modules/node-watch": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz",
"integrity": "sha512-UWblPYuZYrkCQCW5PxAwYSxaELNBLUckrTBBk8xr1/bUgyOkYYTsUcV4e3ytcazFEOyiRyiUrsG37pu6I0I05g==",
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.2.tgz",
"integrity": "sha512-g53VjSARRv1JdST0LZRIg8RiuLr1TaBbVPsVvxh0/0Ymvi0xYUjDuoqQQAWtHJQUXhiShowPT/aXKNeHBcyQsw==",
"dev": true,
"engines": {
"node": ">=6"
@@ -6351,12 +6397,6 @@
"node": ">= 0.10"
}
},
"node_modules/num2fraction": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
"integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
"dev": true
},
"node_modules/number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@@ -6790,9 +6830,9 @@
}
},
"node_modules/path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/path-root": {
@@ -6836,6 +6876,12 @@
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
"dev": true
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
"node_modules/picomatch": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
@@ -6952,34 +6998,29 @@
}
},
"node_modules/postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
"integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz",
"integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==",
"dev": true,
"dependencies": {
"chalk": "^2.4.1",
"source-map": "^0.6.1",
"supports-color": "^5.4.0"
"nanoid": "^3.3.1",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": ">=4.0.0"
"node": "^10 || ^12 || >=14"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
}
},
"node_modules/postcss-value-parser": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"node_modules/postcss/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -7100,15 +7141,14 @@
}
},
"node_modules/qunit": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/qunit/-/qunit-2.15.0.tgz",
"integrity": "sha512-9ZoOILeyRZzrdvy2m7M4S76bneGD75Bh4B2aot3uKRKZuoEvA9gevvzU339L805Ys0AN2C7cnAV9nIBD5t72IQ==",
"version": "2.17.2",
"resolved": "https://registry.npmjs.org/qunit/-/qunit-2.17.2.tgz",
"integrity": "sha512-17isVvuOmALzsPjiV7wFg/6O5vJYXBrQZPwocfQSSh0I/rXvfX7bKMFJ4GMVW3U4P8r2mBeUy8EAngti4QD2Vw==",
"dev": true,
"dependencies": {
"commander": "7.1.0",
"js-reporters": "2.0.0",
"node-watch": "0.7.1",
"tiny-glob": "0.2.8"
"commander": "7.2.0",
"node-watch": "0.7.2",
"tiny-glob": "0.2.9"
},
"bin": {
"qunit": "bin/qunit.js"
@@ -7671,9 +7711,9 @@
"dev": true
},
"node_modules/sass": {
"version": "1.32.13",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.32.13.tgz",
"integrity": "sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==",
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.42.1.tgz",
"integrity": "sha512-/zvGoN8B7dspKc5mC6HlaygyCBRvnyzzgD5khiaCfglWztY99cYoiTUksVx11NlnemrcfH5CEaCpsUKoW0cQqg==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0"
@@ -8328,6 +8368,15 @@
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-resolve": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
@@ -8788,9 +8837,9 @@
}
},
"node_modules/tiny-glob": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.8.tgz",
"integrity": "sha512-vkQP7qOslq63XRX9kMswlby99kyO5OvKptw7AMwBVMjXEI7Tb61eoI5DydyEMOseyGS5anDN1VPoVxEvH01q8w==",
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
"dev": true,
"dependencies": {
"globalyzer": "0.1.0",
@@ -9462,9 +9511,9 @@
}
},
"node_modules/ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
"dev": true,
"dependencies": {
"async-limiter": "~1.0.0"
@@ -10824,9 +10873,9 @@
}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
@@ -11042,29 +11091,17 @@
"dev": true
},
"autoprefixer": {
"version": "8.6.5",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz",
"integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==",
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
"integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==",
"dev": true,
"requires": {
"browserslist": "^3.2.8",
"caniuse-lite": "^1.0.30000864",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001297",
"fraction.js": "^4.1.2",
"normalize-range": "^0.1.2",
"num2fraction": "^1.2.2",
"postcss": "^6.0.23",
"postcss-value-parser": "^3.2.3"
},
"dependencies": {
"browserslist": {
"version": "3.2.8",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
"integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30000844",
"electron-to-chromium": "^1.3.47"
}
}
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
}
},
"babel-plugin-dynamic-import-node": {
@@ -11224,16 +11261,16 @@
}
},
"browserslist": {
"version": "4.16.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
"version": "4.19.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz",
"integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001219",
"colorette": "^1.2.2",
"electron-to-chromium": "^1.3.723",
"caniuse-lite": "^1.0.30001312",
"electron-to-chromium": "^1.4.71",
"escalade": "^3.1.1",
"node-releases": "^1.1.71"
"node-releases": "^2.0.2",
"picocolors": "^1.0.0"
}
},
"buffer-crc32": {
@@ -11306,9 +11343,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001228",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz",
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
"version": "1.0.30001374",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
"dev": true
},
"chalk": {
@@ -11565,12 +11602,6 @@
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
"dev": true
},
"colorette": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
"dev": true
},
"colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
@@ -11578,9 +11609,9 @@
"dev": true
},
"commander": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz",
"integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==",
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true
},
"commondir": {
@@ -11882,9 +11913,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.3.732",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.732.tgz",
"integrity": "sha512-qKD5Pbq+QMk4nea4lMuncUMhpEiQwaJyCW7MrvissnRcBDENhVfDmAqQYRQ3X525oTzhar9Zh1cK0L2d1UKYcw==",
"version": "1.4.73",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz",
"integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==",
"dev": true
},
"emoji-regex": {
@@ -12677,6 +12708,12 @@
"for-in": "^1.0.1"
}
},
"fraction.js": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz",
"integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==",
"dev": true
},
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -12924,17 +12961,39 @@
}
},
"gulp-autoprefixer": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-5.0.0.tgz",
"integrity": "sha1-gjfCeKaXdScKHK/n1vEBz81YVUQ=",
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-8.0.0.tgz",
"integrity": "sha512-sVR++PIaXpa81p52dmmA/jt50bw0egmylK5mjagfgOJ8uLDGaF9tHyzvetkY9Uo0gBZUS5sVqN3kX/GlUKOyog==",
"dev": true,
"requires": {
"autoprefixer": "^8.0.0",
"fancy-log": "^1.3.2",
"autoprefixer": "^10.2.6",
"fancy-log": "^1.3.3",
"plugin-error": "^1.0.1",
"postcss": "^6.0.1",
"through2": "^2.0.0",
"vinyl-sourcemaps-apply": "^0.2.0"
"postcss": "^8.3.0",
"through2": "^4.0.2",
"vinyl-sourcemaps-apply": "^0.2.1"
},
"dependencies": {
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dev": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"through2": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
"integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
"dev": true,
"requires": {
"readable-stream": "3"
}
}
}
},
"gulp-clean-css": {
@@ -14033,12 +14092,6 @@
}
}
},
"js-reporters": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/js-reporters/-/js-reporters-2.0.0.tgz",
"integrity": "sha512-VJd/86niT7GzsaVc+Yxrs8QPrYl1orzv8bYZPuSOtxU6rk/pv8aOXTcIa7HaANvtvdLMTsZspAiucNQ6T2QFHw==",
"dev": true
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -14306,9 +14359,9 @@
}
},
"marked": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-2.0.3.tgz",
"integrity": "sha512-5otztIIcJfPc2qGTN8cVtOJEjNJZ0jwa46INMagrYfk0EvqtRuEHLsEe0LrFS0/q+ZRKT0+kXK7P2T1AN5lWRA==",
"version": "4.0.12",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz",
"integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==",
"dev": true
},
"matchdep": {
@@ -14515,6 +14568,12 @@
"dev": true,
"optional": true
},
"nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"dev": true
},
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -14595,9 +14654,9 @@
"dev": true
},
"node-qunit-puppeteer": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/node-qunit-puppeteer/-/node-qunit-puppeteer-2.0.3.tgz",
"integrity": "sha512-G4mWn3RBQ+JPzCNWzFQ4r6RUUZqj52D5E3Z7wxqRi5b4daph0Alk/mgBpAQqZq7TVR1oV2emnN0Bk0EgYz/4gw==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-qunit-puppeteer/-/node-qunit-puppeteer-2.1.0.tgz",
"integrity": "sha512-53ytjfu+t51r9qbOsek5D9biAlGO808Pp6b1gGdg/fcGJGFZIJNHoVpFF3OLRe7IUXA9QjhsQL9IkK4NGenHCA==",
"dev": true,
"requires": {
"colors": "^1.4.0",
@@ -14605,15 +14664,15 @@
}
},
"node-releases": {
"version": "1.1.72",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
"integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
"integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
"dev": true
},
"node-watch": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.1.tgz",
"integrity": "sha512-UWblPYuZYrkCQCW5PxAwYSxaELNBLUckrTBBk8xr1/bUgyOkYYTsUcV4e3ytcazFEOyiRyiUrsG37pu6I0I05g==",
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/node-watch/-/node-watch-0.7.2.tgz",
"integrity": "sha512-g53VjSARRv1JdST0LZRIg8RiuLr1TaBbVPsVvxh0/0Ymvi0xYUjDuoqQQAWtHJQUXhiShowPT/aXKNeHBcyQsw==",
"dev": true
},
"normalize-package-data": {
@@ -14657,12 +14716,6 @@
"once": "^1.3.2"
}
},
"num2fraction": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
"integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
"dev": true
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@@ -14986,9 +15039,9 @@
"peer": true
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"path-root": {
@@ -15023,6 +15076,12 @@
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
"dev": true
},
"picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
"picomatch": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
@@ -15108,28 +15167,20 @@
"dev": true
},
"postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
"integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz",
"integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
"source-map": "^0.6.1",
"supports-color": "^5.4.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
"nanoid": "^3.3.1",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
},
"postcss-value-parser": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"prelude-ls": {
@@ -15229,15 +15280,14 @@
}
},
"qunit": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/qunit/-/qunit-2.15.0.tgz",
"integrity": "sha512-9ZoOILeyRZzrdvy2m7M4S76bneGD75Bh4B2aot3uKRKZuoEvA9gevvzU339L805Ys0AN2C7cnAV9nIBD5t72IQ==",
"version": "2.17.2",
"resolved": "https://registry.npmjs.org/qunit/-/qunit-2.17.2.tgz",
"integrity": "sha512-17isVvuOmALzsPjiV7wFg/6O5vJYXBrQZPwocfQSSh0I/rXvfX7bKMFJ4GMVW3U4P8r2mBeUy8EAngti4QD2Vw==",
"dev": true,
"requires": {
"commander": "7.1.0",
"js-reporters": "2.0.0",
"node-watch": "0.7.1",
"tiny-glob": "0.2.8"
"commander": "7.2.0",
"node-watch": "0.7.2",
"tiny-glob": "0.2.9"
}
},
"randombytes": {
@@ -15679,9 +15729,9 @@
"dev": true
},
"sass": {
"version": "1.32.13",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.32.13.tgz",
"integrity": "sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==",
"version": "1.42.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.42.1.tgz",
"integrity": "sha512-/zvGoN8B7dspKc5mC6HlaygyCBRvnyzzgD5khiaCfglWztY99cYoiTUksVx11NlnemrcfH5CEaCpsUKoW0cQqg==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0"
@@ -16219,6 +16269,12 @@
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
},
"source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true
},
"source-map-resolve": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
@@ -16611,9 +16667,9 @@
"dev": true
},
"tiny-glob": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.8.tgz",
"integrity": "sha512-vkQP7qOslq63XRX9kMswlby99kyO5OvKptw7AMwBVMjXEI7Tb61eoI5DydyEMOseyGS5anDN1VPoVxEvH01q8w==",
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
"dev": true,
"requires": {
"globalyzer": "0.1.0",
@@ -17161,9 +17217,9 @@
}
},
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
"integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
"dev": true,
"requires": {
"async-limiter": "~1.0.0"

View File

@@ -1,6 +1,6 @@
{
"name": "reveal.js",
"version": "4.1.3",
"version": "4.4.0",
"description": "The HTML Presentation Framework",
"homepage": "https://revealjs.com",
"subdomain": "revealjs",
@@ -42,7 +42,7 @@
"fitty": "^2.3.0",
"glob": "^7.1.7",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^5.0.0",
"gulp-autoprefixer": "^8.0.0",
"gulp-clean-css": "^4.2.0",
"gulp-connect": "^5.7.0",
"gulp-eslint": "^6.0.0",
@@ -50,15 +50,15 @@
"gulp-tap": "^2.0.0",
"gulp-zip": "^4.2.0",
"highlight.js": "^10.0.3",
"marked": "^2.0.3",
"node-qunit-puppeteer": "^2.0.1",
"qunit": "^2.10.0",
"marked": "^4.0.12",
"node-qunit-puppeteer": "^2.1.0",
"qunit": "^2.17.2",
"rollup": "^2.48.0",
"rollup-plugin-terser": "^7.0.2",
"sass": "^1.32.13",
"sass": "^1.39.2",
"yargs": "^15.1.0"
},
"browserslist": "> 0.5%, IE 11, not dead",
"browserslist": "> 2%, not dead",
"eslintConfig": {
"env": {
"browser": true,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
import hljs from 'highlight.js'
import hljs from 'highlight.js';
/* highlightjs-line-numbers.js 2.8.0 | (C) 2018 Yauheni Pakala | MIT License | github.com/wcoder/highlightjs-line-numbers.js */
!function(r,o){"use strict";var e,i="hljs-ln",l="hljs-ln-line",h="hljs-ln-code",s="hljs-ln-numbers",c="hljs-ln-n",m="data-line-number",a=/\r\n|\r|\n/g;function u(e){for(var n=e.toString(),t=e.anchorNode;"TD"!==t.nodeName;)t=t.parentNode;for(var r=e.focusNode;"TD"!==r.nodeName;)r=r.parentNode;var o=parseInt(t.dataset.lineNumber),a=parseInt(r.dataset.lineNumber);if(o==a)return n;var i,l=t.textContent,s=r.textContent;for(a<o&&(i=o,o=a,a=i,i=l,l=s,s=i);0!==n.indexOf(l);)l=l.slice(1);for(;-1===n.lastIndexOf(s);)s=s.slice(0,-1);for(var c=l,u=function(e){for(var n=e;"TABLE"!==n.nodeName;)n=n.parentNode;return n}(t),d=o+1;d<a;++d){var f=p('.{0}[{1}="{2}"]',[h,m,d]);c+="\n"+u.querySelector(f).textContent}return c+="\n"+s}function n(e){try{var n=o.querySelectorAll("code.hljs,code.nohighlight");for(var t in n)n.hasOwnProperty(t)&&(n[t].classList.contains("nohljsln")||d(n[t],e))}catch(e){r.console.error("LineNumbers error: ",e)}}function d(e,n){if("object"==typeof e)e.innerHTML=f(e,n)}function f(e,n){var t,r,o=(t=e,{singleLine:function(e){return!!e.singleLine&&e.singleLine}(r=(r=n)||{}),startFrom:function(e,n){var t=1;isFinite(n.startFrom)&&(t=n.startFrom);var r=function(e,n){return e.hasAttribute(n)?e.getAttribute(n):null}(e,"data-ln-start-from");return null!==r&&(t=function(e,n){if(!e)return n;var t=Number(e);return isFinite(t)?t:n}(r,1)),t}(t,r)});return function e(n){var t=n.childNodes;for(var r in t){var o;t.hasOwnProperty(r)&&(o=t[r],0<(o.textContent.trim().match(a)||[]).length&&(0<o.childNodes.length?e(o):v(o.parentNode)))}}(e),function(e,n){var t=g(e);""===t[t.length-1].trim()&&t.pop();if(1<t.length||n.singleLine){for(var r="",o=0,a=t.length;o<a;o++)r+=p('<tr><td class="{0} {1}" {3}="{5}"><div class="{2}" {3}="{5}"></div></td><td class="{0} {4}" {3}="{5}">{6}</td></tr>',[l,s,c,m,h,o+n.startFrom,0<t[o].length?t[o]:" "]);return p('<table class="{0}">{1}</table>',[i,r])}return e}(e.innerHTML,o)}function v(e){var n=e.className;if(/hljs-/.test(n)){for(var t=g(e.innerHTML),r=0,o="";r<t.length;r++){o+=p('<span class="{0}">{1}</span>\n',[n,0<t[r].length?t[r]:" "])}e.innerHTML=o.trim()}}function g(e){return 0===e.length?[]:e.split(a)}function p(e,t){return e.replace(/\{(\d+)\}/g,function(e,n){return void 0!==t[n]?t[n]:e})}hljs?(hljs.initLineNumbersOnLoad=function(e){"interactive"===o.readyState||"complete"===o.readyState?n(e):r.addEventListener("DOMContentLoaded",function(){n(e)})},hljs.lineNumbersBlock=d,hljs.lineNumbersValue=function(e,n){if("string"!=typeof e)return;var t=document.createElement("code");return t.innerHTML=e,f(t,n)},(e=o.createElement("style")).type="text/css",e.innerHTML=p(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[i,c,m]),o.getElementsByTagName("head")[0].appendChild(e)):r.console.error("highlight.js not detected!"),document.addEventListener("copy",function(e){var n,t=window.getSelection();!function(e){for(var n=e;n;){if(n.className&&-1!==n.className.indexOf("hljs-ln-code"))return 1;n=n.parentNode}}(t.anchorNode)||(n=-1!==window.navigator.userAgent.indexOf("Edge")?u(t):t.toString(),e.clipboardData.setData("text/plain",n),e.preventDefault())})}(window,document);
/* highlightjs-line-numbers.js 2.6.0 | (C) 2018 Yauheni Pakala | MIT License | github.com/wcoder/highlightjs-line-numbers.js */
/* Edited by Hakim for reveal.js; removed async timeout */
!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<l;i++)r+=g('<tr><td class="{0}"><div class="{1} {2}" {3}="{5}"></div></td><td class="{4}"><div class="{1}">{6}</div></td></tr>',[j,m,L,b,p,i+1,t[i].length>0?t[i]:" "]);return g('<table class="{0}">{1}</table>',[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="";r<t.length;r++){var l=t[r].length>0?t[r]:" ";i+=g('<span class="{0}">{1}</span>\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);
/*!
* reveal.js plugin that adds syntax highlight support.
@@ -16,10 +16,10 @@ const Plugin = {
HIGHLIGHT_LINE_DELIMITER: ',',
HIGHLIGHT_LINE_RANGE_DELIMITER: '-',
hljs: hljs,
hljs,
/**
* Highlights code blocks withing the given deck.
* Highlights code blocks within the given deck.
*
* Note that this can be called multiple times if
* there are multiple presentations on one page.
@@ -30,6 +30,7 @@ const Plugin = {
// Read the plugin config options and provide fallbacks
let config = reveal.getConfig().highlight || {};
config.highlightOnLoad = typeof config.highlightOnLoad === 'boolean' ? config.highlightOnLoad : true;
config.escapeHTML = typeof config.escapeHTML === 'boolean' ? config.escapeHTML : true;
@@ -61,12 +62,20 @@ const Plugin = {
hljs.highlightElement( event.currentTarget );
}, false );
if( config.highlightOnLoad ) {
Plugin.highlightBlock( block );
}
} );
// Triggers a callback function before we trigger highlighting
if( typeof config.beforeHighlight === 'function' ) {
config.beforeHighlight( hljs );
}
// Run initial highlighting for all code
if( config.highlightOnLoad ) {
Array.from( reveal.getRevealElement().querySelectorAll( 'pre code' ) ).forEach( block => {
Plugin.highlightBlock( block );
} );
}
// If we're printing to PDF, scroll the code highlights of
// all blocks in the deck into view at once
reveal.on( 'pdf-ready', function() {
@@ -97,7 +106,7 @@ const Plugin = {
var scrollState = { currentBlock: block };
// If there is at least one highlight step, generate
// If there is more than one highlight step, generate
// fragments
var highlightSteps = Plugin.deserializeHighlightSteps( block.getAttribute( 'data-line-numbers' ) );
if( highlightSteps.length > 1 ) {
@@ -133,7 +142,7 @@ const Plugin = {
} );
block.removeAttribute( 'data-fragment-index' )
block.removeAttribute( 'data-fragment-index' );
block.setAttribute( 'data-line-numbers', Plugin.serializeHighlightSteps( [ highlightSteps[0] ] ) );
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
* of external markdown documents.
*/
import marked from 'marked'
import { marked } from 'marked';
const DEFAULT_SLIDE_SEPARATOR = '\r?\n---\r?\n',
DEFAULT_NOTES_SEPARATOR = 'notes?:',

96
plugin/math/katex.js Executable file
View File

@@ -0,0 +1,96 @@
/**
* A plugin which enables rendering of math equations inside
* of reveal.js slides. Essentially a thin wrapper for KaTeX.
*
* @author Hakim El Hattab
* @author Gerhard Burger
*/
export const KaTeX = () => {
let deck;
let defaultOptions = {
version: 'latest',
delimiters: [
{left: '$$', right: '$$', display: true}, // Note: $$ has to come before $
{left: '$', right: '$', display: false},
{left: '\\(', right: '\\)', display: false},
{left: '\\[', right: '\\]', display: true}
],
ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre']
}
const loadCss = src => {
let link = document.createElement('link');
link.rel = 'stylesheet';
link.href = src;
document.head.appendChild(link);
};
/**
* Loads a JavaScript file and returns a Promise for when it is loaded
* Credits: https://aaronsmith.online/easily-load-an-external-script-using-javascript/
*/
const loadScript = src => {
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.type = 'text/javascript'
script.onload = resolve
script.onerror = reject
script.src = src
document.head.append(script)
})
};
async function loadScripts(urls) {
for(const url of urls) {
await loadScript(url);
}
}
return {
id: 'katex',
init: function (reveal) {
deck = reveal;
let revealOptions = deck.getConfig().katex || {};
let options = {...defaultOptions, ...revealOptions};
const {local, version, extensions, ...katexOptions} = options;
let baseUrl = options.local || 'https://cdn.jsdelivr.net/npm/katex';
let versionString = options.local ? '' : '@' + options.version;
let cssUrl = baseUrl + versionString + '/dist/katex.min.css';
let katexUrl = baseUrl + versionString + '/dist/katex.min.js';
let mhchemUrl = baseUrl + versionString + '/dist/contrib/mhchem.min.js'
let karUrl = baseUrl + versionString + '/dist/contrib/auto-render.min.js';
let katexScripts = [katexUrl];
if(options.extensions && options.extensions.includes("mhchem")) {
katexScripts.push(mhchemUrl);
}
katexScripts.push(karUrl);
const renderMath = () => {
renderMathInElement(reveal.getSlidesElement(), katexOptions);
deck.layout();
}
loadCss(cssUrl);
// For some reason dynamically loading with defer attribute doesn't result in the expected behavior, the below code does
loadScripts(katexScripts).then(() => {
if( deck.isReady() ) {
renderMath();
}
else {
deck.on( 'ready', renderMath.bind( this ) );
}
});
}
}
};

View File

@@ -1 +1,6 @@
function e(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 t(t){for(var r=1;r<arguments.length;r++){var a=null!=arguments[r]?arguments[r]:{};r%2?e(Object(a),!0).forEach((function(e){n(t,e,a[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(a)):e(Object(a)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(a,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}export default function(){var e,n={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"math",init:function(r){var a=(e=r).getConfig().math||{},o=t(t({},n),a),c=(o.mathjax||"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js")+"?config="+(o.config||"TeX-AMS_HTML-full");o.tex2jax=t(t({},n.tex2jax),a.tex2jax),o.mathjax=o.config=null,function(e,t){var n=this,r=document.querySelector("head"),a=document.createElement("script");a.type="text/javascript",a.src=e;var o=function(){"function"==typeof t&&(t.call(),t=null)};a.onload=o,a.onreadystatechange=function(){"loaded"===n.readyState&&o()},r.appendChild(a)}(c,(function(){MathJax.Hub.Config(o),MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.getRevealElement()]),MathJax.Hub.Queue(e.layout),e.on("slidechanged",(function(e){MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.currentSlide])}))}))}}}
const t=()=>{let t,e={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"mathjax2",init:function(a){t=a;let n=t.getConfig().mathjax2||t.getConfig().math||{},i={...e,...n},s=(i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js")+"?config="+(i.config||"TeX-AMS_HTML-full");i.tex2jax={...e.tex2jax,...n.tex2jax},i.mathjax=i.config=null,function(t,e){let a=document.querySelector("head"),n=document.createElement("script");n.type="text/javascript",n.src=t;let i=()=>{"function"==typeof e&&(e.call(),e=null)};n.onload=i,n.onreadystatechange=()=>{"loaded"===this.readyState&&i()},a.appendChild(n)}(s,(function(){MathJax.Hub.Config(i),MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.getRevealElement()]),MathJax.Hub.Queue(t.layout),t.on("slidechanged",(function(t){MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.currentSlide])}))}))}}},e=t;
/*!
* This plugin is a wrapper for the MathJax2,
* MathJax3 and KaTeX typesetter plugins.
*/
var a=Plugin=Object.assign(e(),{KaTeX:()=>{let t,e={version:"latest",delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredTags:["script","noscript","style","textarea","pre"]};const a=t=>new Promise(((e,a)=>{const n=document.createElement("script");n.type="text/javascript",n.onload=e,n.onerror=a,n.src=t,document.head.append(n)}));return{id:"katex",init:function(n){t=n;let i=t.getConfig().katex||{},s={...e,...i};const{local:l,version:o,extensions:r,...c}=s;let d=s.local||"https://cdn.jsdelivr.net/npm/katex",p=s.local?"":"@"+s.version,u=d+p+"/dist/katex.min.css",h=d+p+"/dist/contrib/mhchem.min.js",x=d+p+"/dist/contrib/auto-render.min.js",m=[d+p+"/dist/katex.min.js"];s.extensions&&s.extensions.includes("mhchem")&&m.push(h),m.push(x);const f=()=>{renderMathInElement(n.getSlidesElement(),c),t.layout()};(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href=t,document.head.appendChild(e)})(u),async function(t){for(const e of t)await a(e)}(m).then((()=>{t.isReady()?f():t.on("ready",f.bind(this))}))}}},MathJax2:t,MathJax3:()=>{let t,e={tex:{inlineMath:[["$","$"],["\\(","\\)"]]},options:{skipHtmlTags:["script","noscript","style","textarea","pre"]},startup:{ready:()=>{MathJax.startup.defaultReady(),MathJax.startup.promise.then((()=>{Reveal.layout()}))}}};return{id:"mathjax3",init:function(a){t=a;let n=t.getConfig().mathjax3||{},i={...e,...n};i.tex={...e.tex,...n.tex},i.options={...e.options,...n.options},i.startup={...e.startup,...n.startup};let s=i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";i.mathjax=null,window.MathJax=i,function(t,e){let a=document.createElement("script");a.type="text/javascript",a.id="MathJax-script",a.src=t,a.async=!0,a.onload=()=>{"function"==typeof e&&(e.call(),e=null)},document.head.appendChild(a)}(s,(function(){Reveal.addEventListener("slidechanged",(function(t){MathJax.typeset()}))}))}}}});export default a;

View File

@@ -1 +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){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 t(t){for(var r=1;r<arguments.length;r++){var a=null!=arguments[r]?arguments[r]:{};r%2?e(Object(a),!0).forEach((function(e){n(t,e,a[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(a)):e(Object(a)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(a,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}return function(){var e,n={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"math",init:function(r){var a=(e=r).getConfig().math||{},o=t(t({},n),a),i=(o.mathjax||"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js")+"?config="+(o.config||"TeX-AMS_HTML-full");o.tex2jax=t(t({},n.tex2jax),a.tex2jax),o.mathjax=o.config=null,function(e,t){var n=this,r=document.querySelector("head"),a=document.createElement("script");a.type="text/javascript",a.src=e;var o=function(){"function"==typeof t&&(t.call(),t=null)};a.onload=o,a.onreadystatechange=function(){"loaded"===n.readyState&&o()},r.appendChild(a)}(i,(function(){MathJax.Hub.Config(o),MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.getRevealElement()]),MathJax.Hub.Queue(e.layout),e.on("slidechanged",(function(e){MathJax.Hub.Queue(["Typeset",MathJax.Hub,e.currentSlide])}))}))}}}}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).RevealMath=e()}(this,(function(){"use strict";const t=()=>{let t,e={messageStyle:"none",tex2jax:{inlineMath:[["$","$"],["\\(","\\)"]],skipTags:["script","noscript","style","textarea","pre"]},skipStartupTypeset:!0};return{id:"mathjax2",init:function(n){t=n;let a=t.getConfig().mathjax2||t.getConfig().math||{},i={...e,...a},s=(i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js")+"?config="+(i.config||"TeX-AMS_HTML-full");i.tex2jax={...e.tex2jax,...a.tex2jax},i.mathjax=i.config=null,function(t,e){let n=document.querySelector("head"),a=document.createElement("script");a.type="text/javascript",a.src=t;let i=()=>{"function"==typeof e&&(e.call(),e=null)};a.onload=i,a.onreadystatechange=()=>{"loaded"===this.readyState&&i()},n.appendChild(a)}(s,(function(){MathJax.Hub.Config(i),MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.getRevealElement()]),MathJax.Hub.Queue(t.layout),t.on("slidechanged",(function(t){MathJax.Hub.Queue(["Typeset",MathJax.Hub,t.currentSlide])}))}))}}},e=t;return Plugin=Object.assign(e(),{KaTeX:()=>{let t,e={version:"latest",delimiters:[{left:"$$",right:"$$",display:!0},{left:"$",right:"$",display:!1},{left:"\\(",right:"\\)",display:!1},{left:"\\[",right:"\\]",display:!0}],ignoredTags:["script","noscript","style","textarea","pre"]};const n=t=>new Promise(((e,n)=>{const a=document.createElement("script");a.type="text/javascript",a.onload=e,a.onerror=n,a.src=t,document.head.append(a)}));return{id:"katex",init:function(a){t=a;let i=t.getConfig().katex||{},s={...e,...i};const{local:o,version:l,extensions:r,...c}=s;let d=s.local||"https://cdn.jsdelivr.net/npm/katex",u=s.local?"":"@"+s.version,p=d+u+"/dist/katex.min.css",h=d+u+"/dist/contrib/mhchem.min.js",x=d+u+"/dist/contrib/auto-render.min.js",m=[d+u+"/dist/katex.min.js"];s.extensions&&s.extensions.includes("mhchem")&&m.push(h),m.push(x);const f=()=>{renderMathInElement(a.getSlidesElement(),c),t.layout()};(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href=t,document.head.appendChild(e)})(p),async function(t){for(const e of t)await n(e)}(m).then((()=>{t.isReady()?f():t.on("ready",f.bind(this))}))}}},MathJax2:t,MathJax3:()=>{let t,e={tex:{inlineMath:[["$","$"],["\\(","\\)"]]},options:{skipHtmlTags:["script","noscript","style","textarea","pre"]},startup:{ready:()=>{MathJax.startup.defaultReady(),MathJax.startup.promise.then((()=>{Reveal.layout()}))}}};return{id:"mathjax3",init:function(n){t=n;let a=t.getConfig().mathjax3||{},i={...e,...a};i.tex={...e.tex,...a.tex},i.options={...e.options,...a.options},i.startup={...e.startup,...a.startup};let s=i.mathjax||"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js";i.mathjax=null,window.MathJax=i,function(t,e){let n=document.createElement("script");n.type="text/javascript",n.id="MathJax-script",n.src=t,n.async=!0,n.onload=()=>{"function"==typeof e&&(e.call(),e=null)},document.head.appendChild(n)}(s,(function(){Reveal.addEventListener("slidechanged",(function(t){MathJax.typeset()}))}))}}}})}));

89
plugin/math/mathjax2.js Normal file
View File

@@ -0,0 +1,89 @@
/**
* A plugin which enables rendering of math equations inside
* of reveal.js slides. Essentially a thin wrapper for MathJax.
*
* @author Hakim El Hattab
*/
export const MathJax2 = () => {
// The reveal.js instance this plugin is attached to
let deck;
let defaultOptions = {
messageStyle: 'none',
tex2jax: {
inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ],
skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ]
},
skipStartupTypeset: true
};
function loadScript( url, callback ) {
let head = document.querySelector( 'head' );
let script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
// Wrapper for callback to make sure it only fires once
let finish = () => {
if( typeof callback === 'function' ) {
callback.call();
callback = null;
}
}
script.onload = finish;
// IE
script.onreadystatechange = () => {
if ( this.readyState === 'loaded' ) {
finish();
}
}
// Normal browsers
head.appendChild( script );
}
return {
id: 'mathjax2',
init: function( reveal ) {
deck = reveal;
let revealOptions = deck.getConfig().mathjax2 || deck.getConfig().math || {};
let options = { ...defaultOptions, ...revealOptions };
let mathjax = options.mathjax || 'https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js';
let config = options.config || 'TeX-AMS_HTML-full';
let url = mathjax + '?config=' + config;
options.tex2jax = { ...defaultOptions.tex2jax, ...revealOptions.tex2jax };
options.mathjax = options.config = null;
loadScript( url, function() {
MathJax.Hub.Config( options );
// Typeset followed by an immediate reveal.js layout since
// the typesetting process could affect slide height
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, deck.getRevealElement() ] );
MathJax.Hub.Queue( deck.layout );
// Reprocess equations in slides when they turn visible
deck.on( 'slidechanged', function( event ) {
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
} );
} );
}
}
};

77
plugin/math/mathjax3.js Normal file
View File

@@ -0,0 +1,77 @@
/**
* A plugin which enables rendering of math equations inside
* of reveal.js slides. Essentially a thin wrapper for MathJax 3
*
* @author Hakim El Hattab
* @author Gerhard Burger
*/
export const MathJax3 = () => {
// The reveal.js instance this plugin is attached to
let deck;
let defaultOptions = {
tex: {
inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ]
},
options: {
skipHtmlTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ]
},
startup: {
ready: () => {
MathJax.startup.defaultReady();
MathJax.startup.promise.then(() => {
Reveal.layout();
});
}
}
};
function loadScript( url, callback ) {
let script = document.createElement( 'script' );
script.type = "text/javascript"
script.id = "MathJax-script"
script.src = url;
script.async = true
// Wrapper for callback to make sure it only fires once
script.onload = () => {
if (typeof callback === 'function') {
callback.call();
callback = null;
}
};
document.head.appendChild( script );
}
return {
id: 'mathjax3',
init: function(reveal) {
deck = reveal;
let revealOptions = deck.getConfig().mathjax3 || {};
let options = {...defaultOptions, ...revealOptions};
options.tex = {...defaultOptions.tex, ...revealOptions.tex}
options.options = {...defaultOptions.options, ...revealOptions.options}
options.startup = {...defaultOptions.startup, ...revealOptions.startup}
let url = options.mathjax || 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js';
options.mathjax = null;
window.MathJax = options;
loadScript( url, function() {
// Reprocess equations in slides when they turn visible
Reveal.addEventListener( 'slidechanged', function( event ) {
MathJax.typeset();
} );
} );
}
}
};

104
plugin/math/plugin.js Executable file → Normal file
View File

@@ -1,91 +1,15 @@
/**
* A plugin which enables rendering of math equations inside
* of reveal.js slides. Essentially a thin wrapper for MathJax.
*
* @author Hakim El Hattab
import {KaTeX} from "./katex";
import {MathJax2} from "./mathjax2";
import {MathJax3} from "./mathjax3";
const defaultTypesetter = MathJax2;
/*!
* This plugin is a wrapper for the MathJax2,
* MathJax3 and KaTeX typesetter plugins.
*/
const Plugin = () => {
// The reveal.js instance this plugin is attached to
let deck;
let defaultOptions = {
messageStyle: 'none',
tex2jax: {
inlineMath: [ [ '$', '$' ], [ '\\(', '\\)' ] ],
skipTags: [ 'script', 'noscript', 'style', 'textarea', 'pre' ]
},
skipStartupTypeset: true
};
function loadScript( url, callback ) {
let head = document.querySelector( 'head' );
let script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
// Wrapper for callback to make sure it only fires once
let finish = () => {
if( typeof callback === 'function' ) {
callback.call();
callback = null;
}
}
script.onload = finish;
// IE
script.onreadystatechange = () => {
if ( this.readyState === 'loaded' ) {
finish();
}
}
// Normal browsers
head.appendChild( script );
}
return {
id: 'math',
init: function( reveal ) {
deck = reveal;
let revealOptions = deck.getConfig().math || {};
let options = { ...defaultOptions, ...revealOptions };
let mathjax = options.mathjax || 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js';
let config = options.config || 'TeX-AMS_HTML-full';
let url = mathjax + '?config=' + config;
options.tex2jax = { ...defaultOptions.tex2jax, ...revealOptions.tex2jax };
options.mathjax = options.config = null;
loadScript( url, function() {
MathJax.Hub.Config( options );
// Typeset followed by an immediate reveal.js layout since
// the typesetting process could affect slide height
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, deck.getRevealElement() ] );
MathJax.Hub.Queue( deck.layout );
// Reprocess equations in slides when they turn visible
deck.on( 'slidechanged', function( event ) {
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
} );
} );
}
}
};
export default Plugin;
export default Plugin = Object.assign( defaultTypesetter(), {
KaTeX,
MathJax2,
MathJax3
} );

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
import speakerViewHTML from './speaker-view.html';
import speakerViewHTML from './speaker-view.html'
import marked from 'marked';
import { marked } from 'marked';
/**
* Handles opening of and synchronization with the reveal.js
@@ -15,141 +15,197 @@ import marked from 'marked';
*/
const Plugin = () => {
let popup = null;
let connectInterval;
let speakerWindow = null;
let deck;
let deck;
/**
* Opens a new speaker view window.
*/
function openSpeakerWindow() {
function openNotes() {
// If a window is already open, focus it
if( speakerWindow && !speakerWindow.closed ) {
speakerWindow.focus();
}
else {
speakerWindow = window.open( 'about:blank', 'reveal.js - Notes', 'width=1100,height=700' );
speakerWindow.marked = marked;
speakerWindow.document.write( speakerViewHTML );
if (popup && !popup.closed) {
popup.focus();
return;
}
if( !speakerWindow ) {
alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' );
return;
}
popup = window.open( 'about:blank', 'reveal.js - Notes', 'width=1100,height=700' );
popup.marked = marked;
popup.document.write( speakerViewHTML );
if( !popup ) {
alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' );
return;
connect();
}
/**
* Connect to the notes window through a postmessage handshake.
* Using postmessage enables us to work in situations where the
* origins differ, such as a presentation being opened from the
* file system.
*/
function connect() {
// Keep trying to connect until we get a 'connected' message back
let connectInterval = setInterval( function() {
popup.postMessage( JSON.stringify( {
namespace: 'reveal-notes',
type: 'connect',
url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search,
state: deck.getState()
} ), '*' );
}, 500 );
}
window.addEventListener( 'message', function( event ) {
let data = JSON.parse( event.data );
if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
clearInterval( connectInterval );
onConnected();
}
if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) {
callRevealApi( data.methodName, data.arguments, data.callId );
}
} );
/**
* Reconnect with an existing speaker view window.
*/
function reconnectSpeakerWindow( reconnectWindow ) {
if( speakerWindow && !speakerWindow.closed ) {
speakerWindow.focus();
}
else {
speakerWindow = reconnectWindow;
window.addEventListener( 'message', onPostMessage );
onConnected();
}
/**
* Calls the specified Reveal.js method with the provided argument
* and then pushes the result to the notes frame.
*/
function callRevealApi( methodName, methodArguments, callId ) {
}
let result = deck[methodName].apply( deck, methodArguments );
popup.postMessage( JSON.stringify( {
/**
* Connect to the notes window through a postmessage handshake.
* Using postmessage enables us to work in situations where the
* origins differ, such as a presentation being opened from the
* file system.
*/
function connect() {
const presentationURL = deck.getConfig().url;
const url = typeof presentationURL === 'string' ? presentationURL :
window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search;
// Keep trying to connect until we get a 'connected' message back
connectInterval = setInterval( function() {
speakerWindow.postMessage( JSON.stringify( {
namespace: 'reveal-notes',
type: 'return',
result: result,
callId: callId
type: 'connect',
state: deck.getState(),
url
} ), '*' );
}, 500 );
window.addEventListener( 'message', onPostMessage );
}
/**
* Calls the specified Reveal.js method with the provided argument
* and then pushes the result to the notes frame.
*/
function callRevealApi( methodName, methodArguments, callId ) {
let result = deck[methodName].apply( deck, methodArguments );
speakerWindow.postMessage( JSON.stringify( {
namespace: 'reveal-notes',
type: 'return',
result,
callId
} ), '*' );
}
/**
* Posts the current slide data to the notes window.
*/
function post( event ) {
let slideElement = deck.getCurrentSlide(),
notesElements = slideElement.querySelectorAll( 'aside.notes' ),
fragmentElement = slideElement.querySelector( '.current-fragment' );
let messageData = {
namespace: 'reveal-notes',
type: 'state',
notes: '',
markdown: false,
whitespace: 'normal',
state: deck.getState()
};
// Look for notes defined in a slide attribute
if( slideElement.hasAttribute( 'data-notes' ) ) {
messageData.notes = slideElement.getAttribute( 'data-notes' );
messageData.whitespace = 'pre-wrap';
}
/**
* Posts the current slide data to the notes window
*/
function post( event ) {
// Look for notes defined in a fragment
if( fragmentElement ) {
let fragmentNotes = fragmentElement.querySelector( 'aside.notes' );
if( fragmentNotes ) {
messageData.notes = fragmentNotes.innerHTML;
messageData.markdown = typeof fragmentNotes.getAttribute( 'data-markdown' ) === 'string';
let slideElement = deck.getCurrentSlide(),
notesElement = slideElement.querySelector( 'aside.notes' ),
fragmentElement = slideElement.querySelector( '.current-fragment' );
let messageData = {
namespace: 'reveal-notes',
type: 'state',
notes: '',
markdown: false,
whitespace: 'normal',
state: deck.getState()
};
// Look for notes defined in a slide attribute
if( slideElement.hasAttribute( 'data-notes' ) ) {
messageData.notes = slideElement.getAttribute( 'data-notes' );
// Ignore other slide notes
notesElements = null;
}
else if( fragmentElement.hasAttribute( 'data-notes' ) ) {
messageData.notes = fragmentElement.getAttribute( 'data-notes' );
messageData.whitespace = 'pre-wrap';
// In case there are slide notes
notesElements = null;
}
}
// Look for notes defined in a fragment
if( fragmentElement ) {
let fragmentNotes = fragmentElement.querySelector( 'aside.notes' );
if( fragmentNotes ) {
notesElement = fragmentNotes;
}
else if( fragmentElement.hasAttribute( 'data-notes' ) ) {
messageData.notes = fragmentElement.getAttribute( 'data-notes' );
messageData.whitespace = 'pre-wrap';
// Look for notes defined in an aside element
if( notesElements ) {
messageData.notes = Array.from(notesElements).map( notesElement => notesElement.innerHTML ).join( '\n' );
messageData.markdown = notesElements[0] && typeof notesElements[0].getAttribute( 'data-markdown' ) === 'string';
}
// In case there are slide notes
notesElement = null;
}
speakerWindow.postMessage( JSON.stringify( messageData ), '*' );
}
/**
* Check if the given event is from the same origin as the
* current window.
*/
function isSameOriginEvent( event ) {
try {
return window.location.origin === event.source.location.origin;
}
catch ( error ) {
return false;
}
}
function onPostMessage( event ) {
// Only allow same-origin messages
// (added 12/5/22 as a XSS safeguard)
if( isSameOriginEvent( event ) ) {
let data = JSON.parse( event.data );
if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
clearInterval( connectInterval );
onConnected();
}
// Look for notes defined in an aside element
if( notesElement ) {
messageData.notes = notesElement.innerHTML;
messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
else if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) {
callRevealApi( data.methodName, data.arguments, data.callId );
}
popup.postMessage( JSON.stringify( messageData ), '*' );
}
/**
* Called once we have established a connection to the notes
* window.
*/
function onConnected() {
}
// Monitor events that trigger a change in state
deck.on( 'slidechanged', post );
deck.on( 'fragmentshown', post );
deck.on( 'fragmenthidden', post );
deck.on( 'overviewhidden', post );
deck.on( 'overviewshown', post );
deck.on( 'paused', post );
deck.on( 'resumed', post );
/**
* Called once we have established a connection to the notes
* window.
*/
function onConnected() {
// Post the initial state
post();
// Monitor events that trigger a change in state
deck.on( 'slidechanged', post );
deck.on( 'fragmentshown', post );
deck.on( 'fragmenthidden', post );
deck.on( 'overviewhidden', post );
deck.on( 'overviewshown', post );
deck.on( 'paused', post );
deck.on( 'resumed', post );
}
connect();
// Post the initial state
post();
}
@@ -164,19 +220,40 @@ const Plugin = () => {
// If the there's a 'notes' query set, open directly
if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
openNotes();
openSpeakerWindow();
}
else {
// Keep listening for speaker view hearbeats. If we receive a
// heartbeat from an orphaned window, reconnect it. This ensures
// that we remain connected to the notes even if the presentation
// is reloaded.
window.addEventListener( 'message', event => {
if( !speakerWindow && typeof event.data === 'string' ) {
let data;
try {
data = JSON.parse( event.data );
}
catch( error ) {}
if( data && data.namespace === 'reveal-notes' && data.type === 'heartbeat' ) {
reconnectSpeakerWindow( event.source );
}
}
});
}
// Open the notes when the 's' key is hit
deck.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() {
openNotes();
openSpeakerWindow();
} );
}
},
open: openNotes
open: openSpeakerWindow
};
};

View File

@@ -1,3 +1,6 @@
<!--
NOTE: You need to build the notes plugin after making changes to this file.
-->
<html lang="en">
<head>
<meta charset="utf-8">
@@ -347,7 +350,9 @@
layoutDropdown,
pendingCalls = {},
lastRevealApiCallId = 0,
connected = false;
connected = false
var connectionStatus = document.querySelector( '#connection-status' );
var SPEAKER_LAYOUTS = {
'default': 'Default',
@@ -358,7 +363,20 @@
setupLayout();
var connectionStatus = document.querySelector( '#connection-status' );
let openerOrigin;
try {
openerOrigin = window.opener.location.origin;
}
catch ( error ) { console.warn( error ) }
// In order to prevent XSS, the speaker view will only run if its
// opener has the same origin as itself
if( window.location.origin !== openerOrigin ) {
connectionStatus.innerHTML = 'Cross origin error.<br>The speaker window can only be opened from the same origin.';
return;
}
var connectionTimeout = setTimeout( function() {
connectionStatus.innerHTML = 'Error connecting to main window.<br>Please try closing and reopening the speaker view.';
}, 5000 );
@@ -395,13 +413,21 @@
}
else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) && currentState !== JSON.stringify( data.state ) ) {
window.opener.postMessage( JSON.stringify({ method: 'setState', args: [ data.state ]} ), '*' );
dispatchStateToMainWindow( data.state );
}
}
} );
/**
* Updates the presentation in the main window to match the state
* of the presentation in the notes window.
*/
const dispatchStateToMainWindow = debounce(( state ) => {
window.opener.postMessage( JSON.stringify({ method: 'setState', args: [ state ]} ), '*' );
}, 500);
/**
* Asynchronously calls the Reveal.js API of the main frame.
*/
@@ -432,6 +458,7 @@
setupKeyboard();
setupNotes();
setupTimer();
setupHeartbeat();
}
}
@@ -533,6 +560,18 @@
}
/**
* We send out a heartbeat at all times to ensure we can
* reconnect with the main presentation window after reloads.
*/
function setupHeartbeat() {
setInterval( () => {
window.opener.postMessage( JSON.stringify({ namespace: 'reveal-notes', type: 'heartbeat'} ), '*' );
}, 1000 );
}
function getTimings( callback ) {
callRevealApi( 'getSlidesAttributes', [], function ( slideAttributes ) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -25,6 +25,12 @@ const Plugin = {
}
} );
},
destroy: () => {
zoom.reset();
}
};
@@ -52,19 +58,11 @@ var zoom = (function(){
panUpdateInterval = -1;
// Check for transform support so that we can fallback otherwise
var supportsTransforms = '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;
var supportsTransforms = 'transform' in document.body.style;
if( supportsTransforms ) {
// The easing that will be applied when we zoom in/out
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';
}
// Zoom out if the user hits escape
@@ -105,10 +103,6 @@ var zoom = (function(){
// Reset
if( scale === 1 ) {
document.body.style.transform = '';
document.body.style.OTransform = '';
document.body.style.msTransform = '';
document.body.style.MozTransform = '';
document.body.style.WebkitTransform = '';
}
// Scale
else {
@@ -116,16 +110,7 @@ var zoom = (function(){
transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')';
document.body.style.transformOrigin = origin;
document.body.style.OTransformOrigin = origin;
document.body.style.msTransformOrigin = origin;
document.body.style.MozTransformOrigin = origin;
document.body.style.WebkitTransformOrigin = origin;
document.body.style.transform = transform;
document.body.style.OTransform = transform;
document.body.style.msTransform = transform;
document.body.style.MozTransform = transform;
document.body.style.WebkitTransform = transform;
}
}
else {

View File

@@ -1,4 +1,11 @@
/*!
* reveal.js Zoom plugin
*/
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();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),o<t?window.scroll(d.x-14/e*(1-o/t),d.y):o>window.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}
const 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}))}))},destroy:()=>{t.reset()}};var t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();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,l)if(1===o)document.body.style.transform="";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.transform=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 c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),o<t?window.scroll(d.x-14/e*(1-o/t),d.y):o>window.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="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,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();
/*!
* zoom.js 0.3 (modified for use with reveal.js)
* http://lab.hakim.se/zoom-js
* MIT licensed
*
* Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
*/export default()=>e;

View File

@@ -1,4 +1,11 @@
!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";
!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).RevealZoom=t()}(this,(function(){"use strict";
/*!
* reveal.js Zoom plugin
*/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();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),t<o?window.scroll(d.x-14/e*(1-t/o),d.y):t>window.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}}));
*/const 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}))}))},destroy:()=>{t.reset()}};var t=function(){var e=1,o=0,n=0,i=-1,d=-1,l="transform"in document.body.style;function s(t,o){var n=r();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,l)if(1===o)document.body.style.transform="";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.transform=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 c(){var t=.12*window.innerWidth,i=.12*window.innerHeight,d=r();n<i?window.scroll(d.x,d.y-14/e*(1-n/i)):n>window.innerHeight-i&&window.scroll(d.x,d.y+(1-(window.innerHeight-n)/i)*(14/e)),o<t?window.scroll(d.x-14/e*(1-o/t),d.y):o>window.innerWidth-t&&window.scroll(d.x+(1-(window.innerWidth-o)/t)*(14/e),d.y)}function r(){return{x:void 0!==window.scrollX?window.scrollX:window.pageXOffset,y:void 0!==window.scrollY?window.scrollY:window.pageYOffset}}return l&&(document.body.style.transition="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,s(o,o.scale),!1!==o.pan&&(i=setTimeout((function(){d=setInterval(c,1e3/60)}),800)))}},out:function(){clearTimeout(i),clearInterval(d),s({x:0,y:0},1),e=1},magnify:function(e){this.to(e)},reset:function(){this.out()},zoomLevel:function(){return e}}}();
/*!
* zoom.js 0.3 (modified for use with reveal.js)
* http://lab.hakim.se/zoom-js
* MIT licensed
*
* Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
*/return()=>e}));

View File

@@ -23,19 +23,19 @@
<section data-auto-animate>
<h1>h1</h1>
<h2>h2</h2>
<h3 style="position: absolute; left: 0;">h3</h2>
<h3 style="position: absolute; left: 0;">h3</h3>
</section>
<section data-auto-animate>
<h1 data-auto-animate-duration="0.1">h1</h1>
<h2 style="opacity: 0;">h2</h2>
<h3 style="position: absolute; left: 100px;">h3</h2>
<h3 style="position: absolute; left: 100px;">h3</h3>
</section>
<section data-auto-animate data-auto-animate-duration="0.1">
<h1>h1</h1>
<h2>h2</h2>
<h3>h3</h2>
<h3>h3</h3>
</section>
<section>

View File

@@ -36,7 +36,7 @@
<section data-background="examples/assets/image2.png" data-notes="speaker notes 2">
<h1>2.1</h1>
</section>
<section>
<section data-background-image="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4gIcSUNDX1BST0ZJTEUAAQEAAAIMbGNtcwIQAABtbnRyUkdCIFhZWiAH3AABABkAAwApADlhY3NwQVBQTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWxjbXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA/">
<h1>2.2</h1>
</section>
<section>
@@ -97,6 +97,11 @@
// 4
Reveal.initialize().then( function() {
// Helper methods
function triggerKeyboardEvent(config) {
document.dispatchEvent( new KeyboardEvent( 'keydown', config ) );
}
// ---------------------------------------------------------------
// DOM TESTS
@@ -336,38 +341,38 @@
Reveal.configure({ hash: true, fragmentInURL: false });
Reveal.slide( 2, 0 );
assert.strictEqual( window.location.hash, '#/2' );
assert.strictEqual( Reveal.getSlidePath(), '/2' );
Reveal.slide( 2, 1 );
assert.strictEqual( window.location.hash, '#/2/1' );
assert.strictEqual( Reveal.getSlidePath(), '/2/1' );
Reveal.slide( 2, 0, 1 );
assert.strictEqual( window.location.hash, '#/2' );
assert.strictEqual( Reveal.getSlidePath(), '/2' );
Reveal.slide( 2, 2, 0 );
assert.strictEqual( window.location.hash, '#/fragments3' );
assert.strictEqual( Reveal.getSlidePath(), '/fragments3' );
Reveal.slide( 2, 2, 1 );
assert.strictEqual( window.location.hash, '#/fragments3' );
assert.strictEqual( Reveal.getSlidePath(), '/fragments3' );
});
QUnit.test( 'Write (fragmentInURL: true)', function( assert ) {
Reveal.configure({ hash: true, fragmentInURL: true });
Reveal.slide( 2, 0, -1 );
assert.strictEqual( window.location.hash, '#/2' );
assert.strictEqual( Reveal.getSlidePath(), '/2' );
Reveal.slide( 2, 1, -1 );
assert.strictEqual( window.location.hash, '#/2/1' );
assert.strictEqual( Reveal.getSlidePath(), '/2/1' );
Reveal.slide( 2, 0, 1 );
assert.strictEqual( window.location.hash, '#/2/0/1' );
assert.strictEqual( Reveal.getSlidePath(), '/2/0/1' );
Reveal.slide( 2, 2, -1 );
assert.strictEqual( window.location.hash, '#/fragments3' );
assert.strictEqual( Reveal.getSlidePath(), '/fragments3' );
Reveal.slide( 2, 2, 1 );
assert.strictEqual( window.location.hash, '#/fragments3/1' );
assert.strictEqual( Reveal.getSlidePath(), '/fragments3/1' );
});
QUnit.test( 'Read', async function( assert ) {
@@ -407,13 +412,41 @@
assert.ok( /X\-SHORTCUT\-X/.test( document.body.innerHTML ), 'binding is added to help overlay' );
Reveal.toggleHelp( false );
let event = new KeyboardEvent( 'keydown', { 'keyCode':88 } );
document.dispatchEvent( event );
triggerKeyboardEvent({ keyCode: 88 });
Reveal.removeKeyBinding( 88 );
// should do nothing
document.dispatchEvent( event );
triggerKeyboardEvent({ keyCode: 88 });
});
QUnit.test( 'Navigation bindings', function( assert ) {
Reveal.slide( 0 );
// right arrow
triggerKeyboardEvent({ keyCode: 39 });
assert.strictEqual( Reveal.getIndices().h, 1 );
// down arrow + shift
triggerKeyboardEvent({ keyCode: 40, shiftKey: true });
assert.strictEqual( Reveal.getIndices().v, 2, 'shift + down arrow goes to last vertical slide' );
// up arrow
triggerKeyboardEvent({ keyCode: 38 });
assert.strictEqual( Reveal.getIndices().v, 1 );
// right arrow + shift
triggerKeyboardEvent({ keyCode: 39, shiftKey: true });
assert.ok( Reveal.isLastSlide(), 'shift + right arrow goes to last horizontal slide' );
// right arrow on slide with fragments
Reveal.slide( 2, 0, -1 );
triggerKeyboardEvent({ keyCode: 39 });
assert.deepEqual( Reveal.getIndices(), { h: 2, v: 0, f: 0 }, 'right arrow shows fragment' );
triggerKeyboardEvent({ keyCode: 39, altKey: true });
assert.strictEqual( Reveal.getIndices().h, 3, 'right arrow skips fragments when alt key is pressed' );
});
// ---------------------------------------------------------------
@@ -694,7 +727,16 @@
Reveal.right();
assert.equal( Reveal.getIndices().h, 0, 'looped from end to start' );
Reveal.configure({ loop: false });
Reveal.configure({ navigationMode: 'linear' });
Reveal.slide( 0, 0 );
Reveal.prev();
assert.notEqual( Reveal.getIndices().h, 0, 'looped from start to end in linear mode' );
Reveal.next();
assert.equal( Reveal.getIndices().h, 0, 'looped from end to start in linear mode' );
Reveal.configure({ loop: false, navigationMode: 'default' });
});
@@ -727,10 +769,12 @@
QUnit.test( 'background images', function( assert ) {
var imageSource1 = Reveal.getSlide( 0 ).getAttribute( 'data-background-image' );
var imageSource2 = Reveal.getSlide( 1, 0 ).getAttribute( 'data-background' );
var imageSource3 = Reveal.getSlide( 1, 1 ).getAttribute( 'data-background-image' );
// check that the images are applied to the background elements
assert.ok( Reveal.getSlideBackground( 0 ).querySelector( '.slide-background-content' ).style.backgroundImage.indexOf( imageSource1 ) !== -1, 'data-background-image worked' );
assert.ok( Reveal.getSlideBackground( 1, 0 ).querySelector( '.slide-background-content' ).style.backgroundImage.indexOf( imageSource2 ) !== -1, 'data-background worked' );
assert.ok( Reveal.getSlideBackground( 1, 1 ).querySelector( '.slide-background-content' ).style.backgroundImage.indexOf( imageSource3 ) !== -1, 'data-background worked' );
});
@@ -739,6 +783,31 @@
QUnit.module( 'Events' );
QUnit.test( 'beforeslidechange', function( assert ) {
var done = assert.async( 2 );
var normalEvent = function( event ) {
assert.ok( true, 'event fired' );
done();
}
var blockingEvent = function( event ) {
event.preventDefault();
assert.ok( true, 'event fired' );
done();
}
Reveal.on( 'beforeslidechange', normalEvent );
Reveal.slide( 2, 0 );
Reveal.off( 'beforeslidechange', normalEvent );
Reveal.on( 'beforeslidechange', blockingEvent );
Reveal.slide( 3, 0 );
Reveal.off( 'beforeslidechange', blockingEvent );
assert.strictEqual( Reveal.getIndices().h, 2, 'preventing "beforeslidechange" blocks navigation ' );
});
QUnit.test( 'slidechanged', function( assert ) {
assert.expect( 3 );
var done = assert.async( 3 );