1
0
mirror of https://github.com/hakimel/reveal.js.git synced 2025-09-18 10:31:30 +02:00

Compare commits

..

105 Commits
4.5.0 ... 5.0.0

Author SHA1 Message Date
Hakim El Hattab
790fd8c29a mute video in scroll demo 2023-10-27 14:57:55 +02:00
Hakim El Hattab
2518301d3e 5.0 2023-10-27 14:50:14 +02:00
Hakim El Hattab
89bf44ba92 remove legacy mousewheel listeners #3489 2023-10-27 10:35:37 +02:00
Hakim El Hattab
adfa3462cc Merge pull request #3489 from quochuy/mousewheelevents
Support to 'wheel' event listener
2023-10-27 09:43:13 +02:00
Hakim El Hattab
68efdf6b03 Merge branch 'master' into mousewheelevents 2023-10-27 09:42:32 +02:00
Hakim El Hattab
cc640a21d3 not important 2023-10-25 21:33:36 +02:00
Hakim El Hattab
c594f9c6ec not so important 2023-10-25 21:30:53 +02:00
Hakim El Hattab
942be4ee42 fix scroll view activation in tests 2023-10-25 14:13:51 +02:00
Hakim El Hattab
c23964274c reader mode -> scroll view, auto-enable below 435px width 2023-10-25 13:58:06 +02:00
Hakim El Hattab
e46bad392a fix scroll snapping in reader mode compact layout 2023-10-25 13:08:41 +02:00
Hakim El Hattab
ff252c984f reader mode now works for embedded decks 2023-10-25 11:32:40 +02:00
Hakim El Hattab
0072845828 ? keyboard shortcut should not trigger when focus is on an editable element fixes #2645 2023-10-25 11:04:53 +02:00
Hakim El Hattab
5b537aa8f8 fix slide numbers not visible in pdf exports 2023-10-24 10:19:59 +02:00
Hakim El Hattab
aa5c03c234 reader mode remembers scroll position when reloading 2023-10-23 13:08:17 +02:00
Hakim El Hattab
ff3244af7a reader mode refactoring 2023-10-23 11:24:50 +02:00
Hakim El Hattab
49c0030392 improved reader progress bar visuals in high density 2023-10-20 21:02:04 +02:00
Hakim El Hattab
51acc830f9 major cleanup of reader mode code 2023-10-20 20:23:31 +02:00
Hakim El Hattab
cc9a36dc25 massive reader mode refactor; adds support for auto-animate + snapping for fragments 2023-10-20 10:18:34 +02:00
Hakim El Hattab
a9031821ef add scroll snap points for reader mode scroll triggers 2023-10-18 11:16:06 +02:00
Hakim El Hattab
c1d64ad8d0 audit fix 2023-10-17 14:03:27 +02:00
Hakim El Hattab
57ce5a5e3d === 2023-10-17 14:03:00 +02:00
Hakim El Hattab
c4e322ce79 don't show reader scroll bar when there is no overflow, reader style tweaks 2023-10-17 13:59:11 +02:00
Hakim El Hattab
836967d8ab prevent extra page at end when printing to pdf, reader mode styling tweaks 2023-10-13 16:02:55 +02:00
Hakim El Hattab
28ef437a89 rebuild assets 2023-10-12 14:05:42 +02:00
Hakim El Hattab
c80b685a88 Merge pull request #3482 from hakimel/feature/reader-mode
Add reader mode
2023-10-12 14:04:44 +02:00
Hakim El Hattab
7108476911 Merge branch 'master' into feature/reader-mode 2023-10-12 14:04:36 +02:00
Hakim El Hattab
b8b55b8d4c readerScrollBar -> readerScrollbar 2023-10-12 14:03:28 +02:00
Hakim El Hattab
a7d0916f28 reader mode accessibility, bug fixes 2023-10-12 13:58:10 +02:00
Hakim El Hattab
198cbc4ace reader mode tweaks 2023-10-12 13:39:44 +02:00
Hakim El Hattab
d802789c4d more accurate scroll trigger positioning in progress bar 2023-10-12 11:09:47 +02:00
Hakim El Hattab
c1b1745200 audit fix 2023-10-11 10:43:15 +02:00
Hakim El Hattab
980b902a9d disable overview while in reader mode 2023-10-11 10:42:47 +02:00
Hakim El Hattab
be5d811914 convert sass controls spacing to css var, full height reader progress bar 2023-10-11 10:01:32 +02:00
Hakim El Hattab
122642fdea reader progress theming, automatically invert based on slide bg 2023-10-11 09:51:03 +02:00
Hakim El Hattab
09f36adc70 mobile tweaks 2023-10-11 08:24:06 +02:00
Hakim El Hattab
2c5a83c945 refactoring 2023-10-10 14:47:08 +02:00
Hakim El Hattab
a6abd0423e finishing touches on reader mode progress bar 2023-10-10 13:34:33 +02:00
Hakim El Hattab
234799114a reader mode progress bar can be dragged to scroll 2023-10-10 11:16:31 +02:00
Hakim El Hattab
f80ee3b917 reader mode progress bar 2023-10-10 10:24:02 +02:00
Hakim El Hattab
1871824fae reader mode; named deeplink support, stay on same slide when reader mode is turned on/off 2023-10-06 11:37:58 +02:00
Hakim El Hattab
1f1ca3a887 refactoring 2023-10-06 10:07:19 +02:00
Hakim El Hattab
d84aa3472e reader mode tests 2023-10-06 09:52:21 +02:00
Hakim El Hattab
ab52d334df add support for responsively activating reader mode via 2023-10-06 09:14:23 +02:00
NGUYEN DINH Quoc-Huy
42a1844d27 Support to 'wheel' event listener 2023-10-06 15:03:32 +11:00
Hakim El Hattab
899a45dff6 update api method name 2023-10-05 14:24:13 +02:00
Hakim El Hattab
3db2340df3 fix issues with active slide logic in reader mode, foundational work for auto-animate support 2023-10-05 14:06:06 +02:00
Hakim El Hattab
88fbfc5751 fix incorrect unit for slide-width/height css variable #1263 2023-09-26 10:20:29 -04:00
Hakim El Hattab
c856fa9db1 dispatch slidechange events in reader mode 2023-09-25 12:32:46 +02:00
Hakim El Hattab
4c9cc89566 refactoring, remove unused layout 2023-09-22 10:31:34 +02:00
Hakim El Hattab
97f2e184c1 fix preload bug 2023-09-21 14:15:46 +02:00
Hakim El Hattab
e49e89a557 reader mode supports scroll snapping, sticky pages with scroll triggers are always full height 2023-09-21 13:35:49 +02:00
Hakim El Hattab
f0950ba9ae rename 'mode' config value to 'view' 2023-09-20 16:11:31 +02:00
Hakim El Hattab
0861b07618 revamped reader mode sticky logic, add option for fullscreen pages 2023-09-20 15:00:15 +02:00
Hakim El Hattab
5de7da7692 reader mode can be turned off without reload, add Reveal.toggleReader() 2023-09-19 11:52:54 +02:00
Hakim El Hattab
db2523db27 add support for aside element notes inside of fragments (fixes #3478) 2023-09-19 09:29:53 +02:00
Hakim El Hattab
eb01f8f3a5 Merge pull request #3477 from skyboyer/3476-data-notes-does-not-work-on-slide-level
Notes plugin: notes from data-notes attribute were not shown
2023-09-19 09:20:19 +02:00
Yevhen Kozlov
cd948d4136 Notes plugin: notes from data-notes attribute were not shown 2023-09-17 23:29:31 +02:00
Hakim El Hattab
07a6cf1249 fix empty slide bug when all slides in a stack are hidden via data-visibility 2023-09-15 13:48:26 +02:00
Hakim El Hattab
4da6f6b30f refactoring, fix preload distance 2023-09-14 15:17:28 +02:00
Hakim El Hattab
eaf5f61318 reader mode; deeplink support, presentation scaling, scroll trigger fixes 2023-09-14 15:03:23 +02:00
Hakim El Hattab
0f27ef40fb revert demo changes to index.html 2023-09-14 13:19:33 +02:00
Hakim El Hattab
f26d31570e separate reader mode into individual controller, add scroll triggers for fragments 2023-09-14 13:00:31 +02:00
Hakim El Hattab
a4b7f9dff7 4.6.1, remove log 2023-09-13 12:23:36 +02:00
Hakim El Hattab
6aa1eae796 foundation for reader mode, activate via 'mode=reader/print' config param 2023-09-12 17:00:56 +02:00
Hakim El Hattab
487cc860f8 fix alpha overlap during scrolled code highlight transitions 2023-09-12 10:35:37 +02:00
Hakim El Hattab
c5307462b0 4.6.0 2023-09-12 09:16:24 +02:00
Hakim El Hattab
fc16cc8b11 add test deck with 500 slides 2023-09-11 10:22:21 +02:00
Hakim El Hattab
03fe25c1f6 Merge pull request #3464 from t-fritsch/fix-dracula-theme-li-marker-colors
fix dracula li markers
2023-09-04 08:53:40 +02:00
Thomas Fritsch
81ea116292 refactor dracula theme sass code 2023-09-02 12:21:54 +02:00
Thomas Fritsch
3a830dd98f fix dracula theme li numbering 2023-09-02 12:19:59 +02:00
Thomas Fritsch
777e2a2d05 fix dracula li markers
replace :before pseudo elements with :marker selector

allows to have different marker based on the level of nesting (as in other themes : disc, square, circle)
2023-09-02 12:03:11 +02:00
Hakim El Hattab
680cf5edb8 add start/stopEmbeddedMedia API methods for controlling playback of video/audio/iframes 2023-08-25 08:51:52 +02:00
Hakim El Hattab
edf6638065 Merge pull request #3457 from t-fritsch/fix-print-font-for-code-blocks
fix code blocks font when printing pdf
2023-08-24 11:32:27 +02:00
Thomas Fritsch
a1d0cdffc4 fix code blocks font when printing pdf
fixes #2867
2023-08-24 11:11:05 +02:00
Hakim El Hattab
064b3c3aa5 Merge pull request #3450 from gildasio/master
Fix dracula's theme list-style on sub-items
2023-08-24 08:29:59 +02:00
Hakim El Hattab
2ab0689aa3 Merge pull request #3456 from menotti/master-1
Update demo.html
2023-08-24 08:27:09 +02:00
Ricardo Menotti
75c0be853c Update demo.html
switch themes keep current slide
2023-08-23 21:49:36 -03:00
Hakim El Hattab
ccbaffc975 build md plugin #3454 2023-08-23 10:22:58 +02:00
Hakim El Hattab
bae6de87ec Merge pull request #3454 from JankariTech/refactor-vars-and-equality
Refactored var to let or const, used strict equality operator
2023-08-22 13:43:56 +02:00
Prarup Gurung
9babaa005f Refactored var to let or const, strict equality 2023-08-22 17:05:12 +05:45
Hakim El Hattab
af1cd9d6a4 Merge pull request #3453 from JankariTech/fixVariablesTypos
fix typos in variable names
2023-08-22 10:14:58 +02:00
Artur Neumann
a3f71b4a9b fix typos in variable names 2023-08-22 13:56:46 +05:45
Gildasio Junior
58881061ab Fix dracula's theme list-style on sub-items 2023-08-16 15:34:57 -03:00
Hakim El Hattab
e1c180565e Merge pull request #3445 from t-fritsch/fix-scss-watch-tasks
fix scss watch tasks broken on syntax error
2023-08-09 15:17:25 +02:00
Hakim El Hattab
b8d97d2537 Merge pull request #3446 from t-fritsch/speed-up-livereload
speed up livereload
2023-08-09 15:12:36 +02:00
Thomas Fritsch
74a5dac34f speed up livereload
connect.reload needs a stream of files to fire, but this stream is irrelevant here and slows refresh time a lot (from ~2ms to 2000ms here)
2023-08-06 22:52:03 +02:00
Thomas Fritsch
f2b0316a91 fix scss watch tasks broken on syntax error
when there is a syntax error in a sass file (theme or core) the npm start command used to hang, forcing the user to stop and restart the task to compile again.
this fix allows to keep the start-task watching/compiling even when there is an error :
- the error is displayed in terminal
- the rest of gulp tasks are not called (no reload in the browser)
- the user can edit the scss files to try a fix without the need to stop/restart the `npm start` command
2023-08-06 18:39:14 +02:00
Hakim El Hattab
92ee97fbfe update markdown default notes separator to ignore inline occurances of 'notes:', closes #1915, closes #2762 2023-08-06 14:02:55 +02:00
Hakim El Hattab
da5682ce51 move markdown default options to top level #3443 2023-08-06 13:55:00 +02:00
Hakim El Hattab
f4e1a8ef50 Merge pull request #3443 from t-fritsch/allow-markdown-default-options-override
adds ability to override markdown plugin default options
2023-08-06 13:50:11 +02:00
Hakim El Hattab
b66121e32b Merge pull request #3444 from t-fritsch/allow-link-to-nested-element-id
add support for links to the id of an element nested inside slide
2023-08-06 13:41:23 +02:00
Hakim El Hattab
bddf79873b Merge pull request #3442 from t-fritsch/allow-theme-subfolders
allow theme subfolders
2023-08-06 13:33:11 +02:00
Hakim El Hattab
ae703c372c Merge pull request #3441 from t-fritsch/fix-livereload-with-root-param
fixes livereload when using root CLI param
2023-08-06 13:27:12 +02:00
Thomas Fritsch
3d1eabba0f build 2023-08-05 16:47:52 +02:00
Thomas Fritsch
27ff199627 add support for links to the id of an element nested inside slide
fixes hakimel/reveal.js#3231
2023-08-05 16:24:22 +02:00
Thomas Fritsch
31174cbaba adds ability to override markdown default options
```js
Reveal.initialize({
    markdown: {
        defaultOptions: {
            verticalSeparator: '\n--\n`,
        }
    }
})
2023-08-05 00:14:15 +02:00
t-fritsch
ba20abf0c3 allow theme subfolders
allows custom themes to import files from subfolders inside the `css/theme/source` folder.

in `css/theme/source/custom-theme.scss` we can now do
```scss
@import `custom-theme/controls`
@import `custom-theme/headings`
...
```
2023-08-03 22:38:03 +02:00
t-fritsch
2dd27b37c6 ignore node_modules for livereload
may allow perf boost
2023-08-03 22:31:07 +02:00
t-fritsch
82d63e0296 fixes livereload when using root CLI param 2023-08-03 22:23:58 +02:00
Hakim El Hattab
c8a7f26229 fix issue where fragment-evel autoslide timing was when multiple fragments share the same index 2023-08-03 16:00:00 +02:00
Hakim El Hattab
12f5ba4c9d auto-slide duration falls back on global setting instead of looking at first fragment 2023-06-16 12:11:46 +02:00
Hakim El Hattab
227f90fa00 fix code block auto-animate bug that caused unmatched lines to appear without fading in 2023-05-31 09:07:10 +02:00
Hakim El Hattab
0d699ec7f5 Merge pull request #3409 from flowolf/add-code-line-offset-to-markdown
[Markdown plugin] add line number offset for code sections to markdown
2023-05-15 14:14:30 +02:00
Florian Klien
bf749ee1da add tests 2023-05-12 15:45:29 +02:00
Florian Klien
0b44308754 add ln-start-from for code sections to markdown 2023-05-12 14:22:00 +02:00
60 changed files with 2837 additions and 540 deletions

View File

@@ -5,7 +5,7 @@
* https://revealjs.com/pdf-export/
*/
html.print-pdf {
html.reveal-print {
* {
-webkit-print-color-adjust: exact;
}
@@ -36,7 +36,6 @@ html.print-pdf {
.reveal pre code {
overflow: hidden !important;
font-family: Courier, 'Courier New', monospace !important;
}
.reveal {
@@ -71,6 +70,10 @@ html.print-pdf {
page-break-after: always;
}
.reveal .slides .pdf-page:last-of-type {
page-break-after: avoid;
}
.reveal .slides section {
visibility: visible !important;
display: block !important;
@@ -146,6 +149,7 @@ html.print-pdf {
display: block;
position: absolute;
font-size: 14px;
visibility: visible;
}
/* This accessibility tool is not useful in PDF and breaks it visually */

View File

@@ -19,6 +19,7 @@ html.reveal-full-page {
height: 100%;
height: 100vh;
height: calc( var(--vh, 1vh) * 100 );
height: 100svh;
overflow: hidden;
}
@@ -31,6 +32,8 @@ html.reveal-full-page {
background-color: #fff;
color: #000;
--r-controls-spacing: 12px;
}
// Force the presentation to cover the full viewport when we
@@ -271,13 +274,11 @@ $controlsArrowAngleActive: 36deg;
}
.reveal .controls {
$spacing: 12px;
display: none;
position: absolute;
top: auto;
bottom: $spacing;
right: $spacing;
bottom: var(--r-controls-spacing);
right: var(--r-controls-spacing);
left: auto;
z-index: 11;
color: #000;
@@ -509,7 +510,9 @@ $controlsArrowAngleActive: 36deg;
// Edge aligned controls layout
@media screen and (min-width: 500px) {
$spacing: 0.8em;
.reveal-viewport {
--r-controls-spacing: 0.8em;
}
.reveal .controls[data-controls-layout="edges"] {
& {
@@ -529,24 +532,24 @@ $controlsArrowAngleActive: 36deg;
.navigate-left {
top: 50%;
left: $spacing;
left: var(--r-controls-spacing);
margin-top: -$controlArrowSize*0.5;
}
.navigate-right {
top: 50%;
right: $spacing;
right: var(--r-controls-spacing);
margin-top: -$controlArrowSize*0.5;
}
.navigate-up {
top: $spacing;
top: var(--r-controls-spacing);
left: 50%;
margin-left: -$controlArrowSize*0.5;
}
.navigate-down {
bottom: $spacing - $controlArrowSpacing + 0.3em;
bottom: calc(var(--r-controls-spacing) - #{$controlArrowSpacing} + 0.3em);
left: 50%;
margin-left: -$controlArrowSize*0.5;
}
@@ -1636,6 +1639,10 @@ $overlayHeaderPadding: 5px;
opacity: 0.4;
}
.reveal .hljs.has-highlights.fragment {
transition: all .2s ease;
}
.reveal .hljs:not(:first-child).fragment {
position: absolute;
top: 0;
@@ -1860,6 +1867,234 @@ $notesWidthPercent: 25%;
}
/*********************************************
* SCROLL VIEW
*********************************************/
.reveal-viewport.loading-scroll-mode {
visibility: hidden;
}
.reveal-viewport.reveal-scroll {
& {
margin: 0 auto;
overflow: auto;
overflow-x: hidden;
overflow-y: auto;
z-index: 1;
--r-scrollbar-width: 7px;
--r-scrollbar-trigger-size: 5px;
--r-controls-spacing: 8px;
}
@media screen and (max-width: 500px) {
--r-scrollbar-width: 3px;
--r-scrollbar-trigger-size: 3px;
}
.controls,
.progress,
.playback,
.backgrounds,
.slide-number,
.speaker-notes {
display: none !important;
}
.reveal {
overflow: visible;
touch-action: manipulation;
}
.slides {
position: static;
pointer-events: initial;
left: auto;
top: auto;
width: 100% !important;
margin: 0;
padding: 0;
overflow: visible;
display: block;
perspective: none;
perspective-origin: 50% 50%;
}
.scroll-page {
position: relative;
width: 100%;
height: calc(var(--page-height) + var(--page-scroll-padding));
z-index: 1;
overflow: visible;
}
.scroll-page-sticky {
position: sticky;
height: var(--page-height);
top: 0px;
}
.scroll-page-content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.scroll-page section {
visibility: visible !important;
display: block !important;
position: absolute !important;
width: var(--slide-width) !important;
height: var(--slide-height) !important;
top: 50% !important;
left: 50% !important;
opacity: 1 !important;
transform: scale(var(--slide-scale)) translate(-50%, -50%) !important;
transform-style: flat !important;
transform-origin: 0 0 !important;
}
.slide-background {
display: block !important;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: auto !important;
visibility: visible;
opacity: 1;
touch-action: manipulation;
}
}
// Chromium
.reveal-viewport.reveal-scroll[data-scrollbar="true"]::-webkit-scrollbar,
.reveal-viewport.reveal-scroll[data-scrollbar="auto"]::-webkit-scrollbar {
display: none;
}
// Firefox
.reveal-viewport.reveal-scroll[data-scrollbar="true"],
.reveal-viewport.reveal-scroll[data-scrollbar="auto"] {
scrollbar-width: none;
}
.reveal.has-dark-background,
.reveal-viewport.has-dark-background {
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal.has-light-background,
.reveal-viewport.has-light-background {
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport.reveal-scroll .scrollbar {
position: sticky;
top: 50%;
z-index: 20;
opacity: 0;
transition: all 0.3s ease;
&.visible,
&:hover {
opacity: 1;
}
.scrollbar-inner {
position: absolute;
width: var(--r-scrollbar-width);
height: calc(var(--viewport-height) - var(--r-controls-spacing) * 2);
right: var(--r-controls-spacing);
top: 0;
transform: translateY(-50%);
border-radius: var(--r-scrollbar-width);
z-index: 10;
}
.scrollbar-playhead {
position: absolute;
width: var(--r-scrollbar-width);
height: var(--r-scrollbar-width);
top: 0;
left: 0;
border-radius: var(--r-scrollbar-width);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
z-index: 11;
transition: background-color 0.2s ease;
}
.scrollbar-slide {
position: absolute;
width: 100%;
background-color: rgba(var(--r-overlay-element-bg-color), 0.2);
box-shadow: 0 0 0px 1px rgba(var(--r-overlay-element-fg-color), 0.1);
border-radius: var(--r-scrollbar-width);
transition: background-color 0.2s ease;
}
// Hit area
.scrollbar-slide:after {
content: '';
position: absolute;
width: 200%;
height: 100%;
top: 0;
left: -50%;
background: rgba( 0, 0, 0, 0 );
z-index: -1;
}
.scrollbar-slide:hover,
.scrollbar-slide.active {
background-color: rgba(var(--r-overlay-element-bg-color), 0.4);
}
.scrollbar-trigger {
position: absolute;
width: 100%;
transition: background-color 0.2s ease;
}
.scrollbar-slide.active.has-triggers {
background-color: rgba(var(--r-overlay-element-bg-color), 0.4);
z-index: 10;
}
.scrollbar-slide.active .scrollbar-trigger:after {
content: '';
position: absolute;
width: var(--r-scrollbar-trigger-size);
height: var(--r-scrollbar-trigger-size);
border-radius: 20px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
transition: transform 0.2s ease, opacity 0.2s ease;
opacity: 0.4;
}
.scrollbar-slide.active .scrollbar-trigger.active:after,
.scrollbar-slide.active .scrollbar-trigger.active ~ .scrollbar-trigger:after {
opacity: 1;
}
.scrollbar-slide.active .scrollbar-trigger ~ .scrollbar-trigger.active:after {
transform: translate(calc( var(--r-scrollbar-width) * -2), 0);
background-color: rgba(var(--r-overlay-element-bg-color), 1);
}
}
/*********************************************
* PRINT STYLES
*********************************************/

View File

@@ -27,6 +27,9 @@ $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: rgba(79, 64, 28, 0.99);
$heading1TextShadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 20px 20px rgba(0,0,0,.15);
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Background generator
@mixin bodyBackground() {
@include radial-gradient( rgba(247,242,211,1), rgba(255,255,255,1) );

View File

@@ -86,47 +86,21 @@ $codeFont: "Fira Code", $systemFontsMono;
--r-list-bullet-color: #{$listBulletColor};
}
.reveal strong, .reveal b {
color: var(--r-bold-color);
.reveal {
strong, b {
color: var(--r-bold-color);
}
em, i, blockquote {
color: var(--r-italic-color);
}
code {
color: var(--r-inline-code-color);
}
// Dracula colored list bullets and numbers
ul, ol {
li::marker {
color: var(--r-list-bullet-color);
}
}
}
.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

@@ -25,6 +25,9 @@ $linkColor: #51483D;
$linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #26351C;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
.reveal a {
line-height: 1.3em;
}

View File

@@ -31,6 +31,9 @@ $linkColor: #00008B;
$linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: rgba(0, 0, 0, 0.99);
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff);

View File

@@ -29,6 +29,9 @@ $linkColor: #3b759e;
$linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #134674;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Fix links so they are not cut off
.reveal a {
line-height: 1.3em;

View File

@@ -51,6 +51,9 @@ $linkColor: $blue;
$linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: $magenta;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Background generator
// @mixin bodyBackground() {
// @include radial-gradient( rgba($base3,1), rgba(lighten($base3, 20%),1) );

View File

@@ -40,6 +40,9 @@ $heading2Size: 1.6em;
$heading3Size: 1.3em;
$heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff);

View File

@@ -37,6 +37,9 @@ $heading2Size: 1.6em;
$heading3Size: 1.3em;
$heading4Size: 1.0em;
$overlayElementBgColor: 0, 0, 0;
$overlayElementFgColor: 240, 240, 240;
// Change text colors against dark slide backgrounds
@include dark-bg-text-color(#fff);

View File

@@ -25,4 +25,6 @@
--r-link-color-hover: #{$linkColorHover};
--r-selection-background-color: #{$selectionBackgroundColor};
--r-selection-color: #{$selectionColor};
--r-overlay-element-bg-color: #{$overlayElementBgColor};
--r-overlay-element-fg-color: #{$overlayElementFgColor};
}

View File

@@ -38,6 +38,11 @@ $linkColorHover: lighten( $linkColor, 20% );
$selectionBackgroundColor: #FF5E99;
$selectionColor: #fff;
// Colors used for UI elements that are overlaid on top of
// the presentation
$overlayElementBgColor: 240, 240, 240;
$overlayElementFgColor: 0, 0, 0;
// Generates the presentation background, can be overridden
// to return a background image or gradient
@mixin bodyBackground() {

View File

@@ -249,17 +249,17 @@
<p>
reveal.js comes with a few themes built in: <br>
<!-- Hacks to swap themes after the page has loaded. Not flexible and only intended for the reveal.js demo deck. -->
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/black.css'); return false;">Black (default)</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/white.css'); return false;">White</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/league.css'); return false;">League</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/sky.css'); return false;">Sky</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/beige.css'); return false;">Beige</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/simple.css'); return false;">Simple</a> <br>
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/serif.css'); return false;">Serif</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/blood.css'); return false;">Blood</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/night.css'); return false;">Night</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/moon.css'); return false;">Moon</a> -
<a href="#" onclick="document.getElementById('theme').setAttribute('href','dist/theme/solarized.css'); return false;">Solarized</a>
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/black.css'); return false;">Black (default)</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/white.css'); return false;">White</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/league.css'); return false;">League</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/sky.css'); return false;">Sky</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/beige.css'); return false;">Beige</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/simple.css'); return false;">Simple</a> <br>
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/serif.css'); return false;">Serif</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/blood.css'); return false;">Blood</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/night.css'); return false;">Night</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/moon.css'); return false;">Moon</a> -
<a href="#/themes" onclick="document.getElementById('theme').setAttribute('href','dist/theme/solarized.css'); return false;">Solarized</a>
</p>
</section>

4
dist/reveal.css vendored

File diff suppressed because one or more lines are too long

4
dist/reveal.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/reveal.js vendored

File diff suppressed because one or more lines are too long

2
dist/reveal.js.map vendored

File diff suppressed because one or more lines are too long

View File

@@ -37,6 +37,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #c0a86e;
--r-selection-background-color: rgba(79, 64, 28, 0.99);
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8dcffc;
--r-selection-background-color: #bee4fd;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {

View File

@@ -36,6 +36,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8dcffc;
--r-selection-background-color: rgba(66, 175, 250, 0.75);
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {

View File

@@ -42,6 +42,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #dd5566;
--r-selection-background-color: #a23;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {

View File

@@ -1,4 +1,3 @@
@charset "UTF-8";
/**
* Dracula Dark theme for reveal.js.
* Based on https://draculatheme.com
@@ -44,6 +43,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #8BE9FD;
--r-selection-background-color: #44475A;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {
@@ -373,42 +374,12 @@ section.has-light-background, section.has-light-background h1, section.has-light
.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: "•";
.reveal ul li::marker, .reveal ol li::marker {
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

@@ -39,6 +39,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #71e9f4;
--r-selection-background-color: #FF5E99;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {

2
dist/theme/moon.css vendored
View File

@@ -44,6 +44,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #78b9e6;
--r-selection-background-color: #d33682;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {

View File

@@ -37,6 +37,8 @@ section.has-light-background, section.has-light-background h1, section.has-light
--r-link-color-hover: #f3d7ac;
--r-selection-background-color: #e7ad52;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {

View File

@@ -40,6 +40,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #8b7c69;
--r-selection-background-color: #26351C;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #0000f1;
--r-selection-background-color: rgba(0, 0, 0, 0.99);
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

2
dist/theme/sky.css vendored
View File

@@ -41,6 +41,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #74a7cb;
--r-selection-background-color: #134674;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

View File

@@ -40,6 +40,8 @@ html * {
--r-link-color-hover: #78b9e6;
--r-selection-background-color: #d33682;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

View File

@@ -39,6 +39,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #6ca0e8;
--r-selection-background-color: #98bdef;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

View File

@@ -36,6 +36,8 @@ section.has-dark-background, section.has-dark-background h1, section.has-dark-ba
--r-link-color-hover: #6ca0e8;
--r-selection-background-color: #98bdef;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 0, 0, 0;
--r-overlay-element-fg-color: 240, 240, 240;
}
.reveal-viewport {

526
examples/500-slides.html Normal file
View File

@@ -0,0 +1,526 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - 500 slides</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../dist/theme/black.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section><h1>1</h1></section>
<section><h1>2</h1></section>
<section><h1>3</h1></section>
<section><h1>4</h1></section>
<section><h1>5</h1></section>
<section><h1>6</h1></section>
<section><h1>7</h1></section>
<section><h1>8</h1></section>
<section><h1>9</h1></section>
<section><h1>10</h1></section>
<section><h1>11</h1></section>
<section><h1>12</h1></section>
<section><h1>13</h1></section>
<section><h1>14</h1></section>
<section><h1>15</h1></section>
<section><h1>16</h1></section>
<section><h1>17</h1></section>
<section><h1>18</h1></section>
<section><h1>19</h1></section>
<section><h1>20</h1></section>
<section><h1>21</h1></section>
<section><h1>22</h1></section>
<section><h1>23</h1></section>
<section><h1>24</h1></section>
<section><h1>25</h1></section>
<section><h1>26</h1></section>
<section><h1>27</h1></section>
<section><h1>28</h1></section>
<section><h1>29</h1></section>
<section><h1>30</h1></section>
<section><h1>31</h1></section>
<section><h1>32</h1></section>
<section><h1>33</h1></section>
<section><h1>34</h1></section>
<section><h1>35</h1></section>
<section><h1>36</h1></section>
<section><h1>37</h1></section>
<section><h1>38</h1></section>
<section><h1>39</h1></section>
<section><h1>40</h1></section>
<section><h1>41</h1></section>
<section><h1>42</h1></section>
<section><h1>43</h1></section>
<section><h1>44</h1></section>
<section><h1>45</h1></section>
<section><h1>46</h1></section>
<section><h1>47</h1></section>
<section><h1>48</h1></section>
<section><h1>49</h1></section>
<section><h1>50</h1></section>
<section><h1>51</h1></section>
<section><h1>52</h1></section>
<section><h1>53</h1></section>
<section><h1>54</h1></section>
<section><h1>55</h1></section>
<section><h1>56</h1></section>
<section><h1>57</h1></section>
<section><h1>58</h1></section>
<section><h1>59</h1></section>
<section><h1>60</h1></section>
<section><h1>61</h1></section>
<section><h1>62</h1></section>
<section><h1>63</h1></section>
<section><h1>64</h1></section>
<section><h1>65</h1></section>
<section><h1>66</h1></section>
<section><h1>67</h1></section>
<section><h1>68</h1></section>
<section><h1>69</h1></section>
<section><h1>70</h1></section>
<section><h1>71</h1></section>
<section><h1>72</h1></section>
<section><h1>73</h1></section>
<section><h1>74</h1></section>
<section><h1>75</h1></section>
<section><h1>76</h1></section>
<section><h1>77</h1></section>
<section><h1>78</h1></section>
<section><h1>79</h1></section>
<section><h1>80</h1></section>
<section><h1>81</h1></section>
<section><h1>82</h1></section>
<section><h1>83</h1></section>
<section><h1>84</h1></section>
<section><h1>85</h1></section>
<section><h1>86</h1></section>
<section><h1>87</h1></section>
<section><h1>88</h1></section>
<section><h1>89</h1></section>
<section><h1>90</h1></section>
<section><h1>91</h1></section>
<section><h1>92</h1></section>
<section><h1>93</h1></section>
<section><h1>94</h1></section>
<section><h1>95</h1></section>
<section><h1>96</h1></section>
<section><h1>97</h1></section>
<section><h1>98</h1></section>
<section><h1>99</h1></section>
<section><h1>100</h1></section>
<section><h1>101</h1></section>
<section><h1>102</h1></section>
<section><h1>103</h1></section>
<section><h1>104</h1></section>
<section><h1>105</h1></section>
<section><h1>106</h1></section>
<section><h1>107</h1></section>
<section><h1>108</h1></section>
<section><h1>109</h1></section>
<section><h1>110</h1></section>
<section><h1>111</h1></section>
<section><h1>112</h1></section>
<section><h1>113</h1></section>
<section><h1>114</h1></section>
<section><h1>115</h1></section>
<section><h1>116</h1></section>
<section><h1>117</h1></section>
<section><h1>118</h1></section>
<section><h1>119</h1></section>
<section><h1>120</h1></section>
<section><h1>121</h1></section>
<section><h1>122</h1></section>
<section><h1>123</h1></section>
<section><h1>124</h1></section>
<section><h1>125</h1></section>
<section><h1>126</h1></section>
<section><h1>127</h1></section>
<section><h1>128</h1></section>
<section><h1>129</h1></section>
<section><h1>130</h1></section>
<section><h1>131</h1></section>
<section><h1>132</h1></section>
<section><h1>133</h1></section>
<section><h1>134</h1></section>
<section><h1>135</h1></section>
<section><h1>136</h1></section>
<section><h1>137</h1></section>
<section><h1>138</h1></section>
<section><h1>139</h1></section>
<section><h1>140</h1></section>
<section><h1>141</h1></section>
<section><h1>142</h1></section>
<section><h1>143</h1></section>
<section><h1>144</h1></section>
<section><h1>145</h1></section>
<section><h1>146</h1></section>
<section><h1>147</h1></section>
<section><h1>148</h1></section>
<section><h1>149</h1></section>
<section><h1>150</h1></section>
<section><h1>151</h1></section>
<section><h1>152</h1></section>
<section><h1>153</h1></section>
<section><h1>154</h1></section>
<section><h1>155</h1></section>
<section><h1>156</h1></section>
<section><h1>157</h1></section>
<section><h1>158</h1></section>
<section><h1>159</h1></section>
<section><h1>160</h1></section>
<section><h1>161</h1></section>
<section><h1>162</h1></section>
<section><h1>163</h1></section>
<section><h1>164</h1></section>
<section><h1>165</h1></section>
<section><h1>166</h1></section>
<section><h1>167</h1></section>
<section><h1>168</h1></section>
<section><h1>169</h1></section>
<section><h1>170</h1></section>
<section><h1>171</h1></section>
<section><h1>172</h1></section>
<section><h1>173</h1></section>
<section><h1>174</h1></section>
<section><h1>175</h1></section>
<section><h1>176</h1></section>
<section><h1>177</h1></section>
<section><h1>178</h1></section>
<section><h1>179</h1></section>
<section><h1>180</h1></section>
<section><h1>181</h1></section>
<section><h1>182</h1></section>
<section><h1>183</h1></section>
<section><h1>184</h1></section>
<section><h1>185</h1></section>
<section><h1>186</h1></section>
<section><h1>187</h1></section>
<section><h1>188</h1></section>
<section><h1>189</h1></section>
<section><h1>190</h1></section>
<section><h1>191</h1></section>
<section><h1>192</h1></section>
<section><h1>193</h1></section>
<section><h1>194</h1></section>
<section><h1>195</h1></section>
<section><h1>196</h1></section>
<section><h1>197</h1></section>
<section><h1>198</h1></section>
<section><h1>199</h1></section>
<section><h1>200</h1></section>
<section><h1>201</h1></section>
<section><h1>202</h1></section>
<section><h1>203</h1></section>
<section><h1>204</h1></section>
<section><h1>205</h1></section>
<section><h1>206</h1></section>
<section><h1>207</h1></section>
<section><h1>208</h1></section>
<section><h1>209</h1></section>
<section><h1>210</h1></section>
<section><h1>211</h1></section>
<section><h1>212</h1></section>
<section><h1>213</h1></section>
<section><h1>214</h1></section>
<section><h1>215</h1></section>
<section><h1>216</h1></section>
<section><h1>217</h1></section>
<section><h1>218</h1></section>
<section><h1>219</h1></section>
<section><h1>220</h1></section>
<section><h1>221</h1></section>
<section><h1>222</h1></section>
<section><h1>223</h1></section>
<section><h1>224</h1></section>
<section><h1>225</h1></section>
<section><h1>226</h1></section>
<section><h1>227</h1></section>
<section><h1>228</h1></section>
<section><h1>229</h1></section>
<section><h1>230</h1></section>
<section><h1>231</h1></section>
<section><h1>232</h1></section>
<section><h1>233</h1></section>
<section><h1>234</h1></section>
<section><h1>235</h1></section>
<section><h1>236</h1></section>
<section><h1>237</h1></section>
<section><h1>238</h1></section>
<section><h1>239</h1></section>
<section><h1>240</h1></section>
<section><h1>241</h1></section>
<section><h1>242</h1></section>
<section><h1>243</h1></section>
<section><h1>244</h1></section>
<section><h1>245</h1></section>
<section><h1>246</h1></section>
<section><h1>247</h1></section>
<section><h1>248</h1></section>
<section><h1>249</h1></section>
<section><h1>250</h1></section>
<section><h1>251</h1></section>
<section><h1>252</h1></section>
<section><h1>253</h1></section>
<section><h1>254</h1></section>
<section><h1>255</h1></section>
<section><h1>256</h1></section>
<section><h1>257</h1></section>
<section><h1>258</h1></section>
<section><h1>259</h1></section>
<section><h1>260</h1></section>
<section><h1>261</h1></section>
<section><h1>262</h1></section>
<section><h1>263</h1></section>
<section><h1>264</h1></section>
<section><h1>265</h1></section>
<section><h1>266</h1></section>
<section><h1>267</h1></section>
<section><h1>268</h1></section>
<section><h1>269</h1></section>
<section><h1>270</h1></section>
<section><h1>271</h1></section>
<section><h1>272</h1></section>
<section><h1>273</h1></section>
<section><h1>274</h1></section>
<section><h1>275</h1></section>
<section><h1>276</h1></section>
<section><h1>277</h1></section>
<section><h1>278</h1></section>
<section><h1>279</h1></section>
<section><h1>280</h1></section>
<section><h1>281</h1></section>
<section><h1>282</h1></section>
<section><h1>283</h1></section>
<section><h1>284</h1></section>
<section><h1>285</h1></section>
<section><h1>286</h1></section>
<section><h1>287</h1></section>
<section><h1>288</h1></section>
<section><h1>289</h1></section>
<section><h1>290</h1></section>
<section><h1>291</h1></section>
<section><h1>292</h1></section>
<section><h1>293</h1></section>
<section><h1>294</h1></section>
<section><h1>295</h1></section>
<section><h1>296</h1></section>
<section><h1>297</h1></section>
<section><h1>298</h1></section>
<section><h1>299</h1></section>
<section><h1>300</h1></section>
<section><h1>301</h1></section>
<section><h1>302</h1></section>
<section><h1>303</h1></section>
<section><h1>304</h1></section>
<section><h1>305</h1></section>
<section><h1>306</h1></section>
<section><h1>307</h1></section>
<section><h1>308</h1></section>
<section><h1>309</h1></section>
<section><h1>310</h1></section>
<section><h1>311</h1></section>
<section><h1>312</h1></section>
<section><h1>313</h1></section>
<section><h1>314</h1></section>
<section><h1>315</h1></section>
<section><h1>316</h1></section>
<section><h1>317</h1></section>
<section><h1>318</h1></section>
<section><h1>319</h1></section>
<section><h1>320</h1></section>
<section><h1>321</h1></section>
<section><h1>322</h1></section>
<section><h1>323</h1></section>
<section><h1>324</h1></section>
<section><h1>325</h1></section>
<section><h1>326</h1></section>
<section><h1>327</h1></section>
<section><h1>328</h1></section>
<section><h1>329</h1></section>
<section><h1>330</h1></section>
<section><h1>331</h1></section>
<section><h1>332</h1></section>
<section><h1>333</h1></section>
<section><h1>334</h1></section>
<section><h1>335</h1></section>
<section><h1>336</h1></section>
<section><h1>337</h1></section>
<section><h1>338</h1></section>
<section><h1>339</h1></section>
<section><h1>340</h1></section>
<section><h1>341</h1></section>
<section><h1>342</h1></section>
<section><h1>343</h1></section>
<section><h1>344</h1></section>
<section><h1>345</h1></section>
<section><h1>346</h1></section>
<section><h1>347</h1></section>
<section><h1>348</h1></section>
<section><h1>349</h1></section>
<section><h1>350</h1></section>
<section><h1>351</h1></section>
<section><h1>352</h1></section>
<section><h1>353</h1></section>
<section><h1>354</h1></section>
<section><h1>355</h1></section>
<section><h1>356</h1></section>
<section><h1>357</h1></section>
<section><h1>358</h1></section>
<section><h1>359</h1></section>
<section><h1>360</h1></section>
<section><h1>361</h1></section>
<section><h1>362</h1></section>
<section><h1>363</h1></section>
<section><h1>364</h1></section>
<section><h1>365</h1></section>
<section><h1>366</h1></section>
<section><h1>367</h1></section>
<section><h1>368</h1></section>
<section><h1>369</h1></section>
<section><h1>370</h1></section>
<section><h1>371</h1></section>
<section><h1>372</h1></section>
<section><h1>373</h1></section>
<section><h1>374</h1></section>
<section><h1>375</h1></section>
<section><h1>376</h1></section>
<section><h1>377</h1></section>
<section><h1>378</h1></section>
<section><h1>379</h1></section>
<section><h1>380</h1></section>
<section><h1>381</h1></section>
<section><h1>382</h1></section>
<section><h1>383</h1></section>
<section><h1>384</h1></section>
<section><h1>385</h1></section>
<section><h1>386</h1></section>
<section><h1>387</h1></section>
<section><h1>388</h1></section>
<section><h1>389</h1></section>
<section><h1>390</h1></section>
<section><h1>391</h1></section>
<section><h1>392</h1></section>
<section><h1>393</h1></section>
<section><h1>394</h1></section>
<section><h1>395</h1></section>
<section><h1>396</h1></section>
<section><h1>397</h1></section>
<section><h1>398</h1></section>
<section><h1>399</h1></section>
<section><h1>400</h1></section>
<section><h1>401</h1></section>
<section><h1>402</h1></section>
<section><h1>403</h1></section>
<section><h1>404</h1></section>
<section><h1>405</h1></section>
<section><h1>406</h1></section>
<section><h1>407</h1></section>
<section><h1>408</h1></section>
<section><h1>409</h1></section>
<section><h1>410</h1></section>
<section><h1>411</h1></section>
<section><h1>412</h1></section>
<section><h1>413</h1></section>
<section><h1>414</h1></section>
<section><h1>415</h1></section>
<section><h1>416</h1></section>
<section><h1>417</h1></section>
<section><h1>418</h1></section>
<section><h1>419</h1></section>
<section><h1>420</h1></section>
<section><h1>421</h1></section>
<section><h1>422</h1></section>
<section><h1>423</h1></section>
<section><h1>424</h1></section>
<section><h1>425</h1></section>
<section><h1>426</h1></section>
<section><h1>427</h1></section>
<section><h1>428</h1></section>
<section><h1>429</h1></section>
<section><h1>430</h1></section>
<section><h1>431</h1></section>
<section><h1>432</h1></section>
<section><h1>433</h1></section>
<section><h1>434</h1></section>
<section><h1>435</h1></section>
<section><h1>436</h1></section>
<section><h1>437</h1></section>
<section><h1>438</h1></section>
<section><h1>439</h1></section>
<section><h1>440</h1></section>
<section><h1>441</h1></section>
<section><h1>442</h1></section>
<section><h1>443</h1></section>
<section><h1>444</h1></section>
<section><h1>445</h1></section>
<section><h1>446</h1></section>
<section><h1>447</h1></section>
<section><h1>448</h1></section>
<section><h1>449</h1></section>
<section><h1>450</h1></section>
<section><h1>451</h1></section>
<section><h1>452</h1></section>
<section><h1>453</h1></section>
<section><h1>454</h1></section>
<section><h1>455</h1></section>
<section><h1>456</h1></section>
<section><h1>457</h1></section>
<section><h1>458</h1></section>
<section><h1>459</h1></section>
<section><h1>460</h1></section>
<section><h1>461</h1></section>
<section><h1>462</h1></section>
<section><h1>463</h1></section>
<section><h1>464</h1></section>
<section><h1>465</h1></section>
<section><h1>466</h1></section>
<section><h1>467</h1></section>
<section><h1>468</h1></section>
<section><h1>469</h1></section>
<section><h1>470</h1></section>
<section><h1>471</h1></section>
<section><h1>472</h1></section>
<section><h1>473</h1></section>
<section><h1>474</h1></section>
<section><h1>475</h1></section>
<section><h1>476</h1></section>
<section><h1>477</h1></section>
<section><h1>478</h1></section>
<section><h1>479</h1></section>
<section><h1>480</h1></section>
<section><h1>481</h1></section>
<section><h1>482</h1></section>
<section><h1>483</h1></section>
<section><h1>484</h1></section>
<section><h1>485</h1></section>
<section><h1>486</h1></section>
<section><h1>487</h1></section>
<section><h1>488</h1></section>
<section><h1>489</h1></section>
<section><h1>490</h1></section>
<section><h1>491</h1></section>
<section><h1>492</h1></section>
<section><h1>493</h1></section>
<section><h1>494</h1></section>
<section><h1>495</h1></section>
<section><h1>496</h1></section>
<section><h1>497</h1></section>
<section><h1>498</h1></section>
<section><h1>499</h1></section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script>
Reveal.initialize({
transition: 'linear'
});
</script>
</body>
</html>

View File

@@ -99,6 +99,25 @@
</script>
</section>
<!-- add optional line count offset, in this case 287 -->
<section data-markdown>
<script type="text/template">
## echo.c
```c [287: 2|4,6]
/* All of the options in this arg are valid, so handle them. */
p = arg + 1;
do {
if (*p == 'n')
nflag = 0;
if (*p == 'e')
eflag = '\\';
} while (*++p);
```
[source](https://git.busybox.net/busybox/tree/coreutils/echo.c?h=1_36_stable#n287)
</script>
</section>
<!-- Images -->
<section data-markdown>
<script type="text/template">

122
examples/scroll.html Normal file
View File

@@ -0,0 +1,122 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Scroll View</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="../dist/reset.css">
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../dist/theme/black.css" id="theme">
<link rel="stylesheet" href="../plugin/highlight/monokai.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section><h1>Scroll View</h1></section>
<section data-background="indigo">
<h2>Scroll triggers</h2>
<ul>
<li class="fragment fade-left">Step one</li>
<li class="fragment fade-left">Step two</li>
<li class="fragment fade-left">Step three</li>
</ul>
</section>
<section data-background-color="#fff"><h2>Scroll bar inverts<br>based on slide bg</h2></section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<h2>Auto-Animate</h2>
<p>Automatically animate matching elements across slides with <a href="https://revealjs.com/auto-animate/">Auto-Animate</a>.</p>
<div class="r-hstack justify-center">
<div data-id="box1" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
<div data-id="box2" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
<div data-id="box3" style="background: #999; width: 50px; height: 50px; margin: 10px; border-radius: 5px;"></div>
</div>
</section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<div class="r-hstack justify-center">
<div data-id="box1" data-auto-animate-delay="0" style="background: cyan; width: 150px; height: 100px; margin: 10px;"></div>
<div data-id="box2" data-auto-animate-delay="0.1" style="background: magenta; width: 150px; height: 100px; margin: 10px;"></div>
<div data-id="box3" data-auto-animate-delay="0.2" style="background: yellow; width: 150px; height: 100px; margin: 10px;"></div>
</div>
<h2 style="margin-top: 20px;">Auto-Animate</h2>
</section>
<section data-auto-animate data-auto-animate-easing="cubic-bezier(0.770, 0.000, 0.175, 1.000)">
<div class="r-stack">
<div data-id="box1" style="background: cyan; width: 300px; height: 300px; border-radius: 200px;"></div>
<div data-id="box2" style="background: magenta; width: 200px; height: 200px; border-radius: 200px;"></div>
<div data-id="box3" style="background: yellow; width: 100px; height: 100px; border-radius: 200px;"></div>
</div>
<h2 style="margin-top: 20px;">Auto-Animate</h2>
</section>
<section data-background-gradient="linear-gradient(to bottom, #283b95, #17b2c3)" id="gradient-bg">
<h2>Gradient Backgrounds</h2>
</section>
<section data-auto-animate>
<h2 data-id="code-title">Scroll triggered code highlights</h2>
<pre data-id="code-animation"><code class="hljs javascript" data-trim data-line-numbers="|4,8-11|17|22-24"><script type="text/template">
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
function SecondExample() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
</script></code></pre>
</section>
<section class="stack">
<section data-background="https://static.slid.es/reveal/image-placeholder.png" id="image-bg">
<h2>Image Backgrounds</h2>
<pre><code class="hljs html">&lt;section data-background="image.png"&gt;</code></pre>
</section>
<section data-background-video-muted data-background-video="https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4,https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.webm">
<h2>Video background</h2>
</section>
</section>
<section><h2>The end</h2></section>
</div>
</div>
<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>
Reveal.initialize({
view: 'scroll',
hash: true,
plugins: [ RevealMarkdown, RevealHighlight, RevealNotes ]
});
</script>
</body>
</html>

View File

@@ -164,11 +164,10 @@ function compileSass() {
sass.render({
data: transformedFile.contents.toString(),
includePaths: ['css/', 'css/theme/template']
file: transformedFile.path,
}, ( err, result ) => {
if( err ) {
console.log( vinylFile.path );
console.log( err.formatted );
callback(err);
}
else {
transformedFile.extname = '.css';
@@ -286,7 +285,7 @@ gulp.task('package', gulp.series(() =>
))
gulp.task('reload', () => gulp.src(['**/*.html', '**/*.md'])
gulp.task('reload', () => gulp.src(['index.html'])
.pipe(connect.reload()));
gulp.task('serve', () => {
@@ -298,14 +297,19 @@ gulp.task('serve', () => {
livereload: true
})
gulp.watch(['**/*.html', '**/*.md'], gulp.series('reload'))
const slidesRoot = root.endsWith('/') ? root : root + '/'
gulp.watch([
slidesRoot + '**/*.html',
slidesRoot + '**/*.md',
`!${slidesRoot}**/node_modules/**`, // ignore node_modules
], gulp.series('reload'))
gulp.watch(['js/**'], gulp.series('js', 'reload', 'eslint'))
gulp.watch(['plugin/**/plugin.js', 'plugin/**/*.html'], gulp.series('plugins', 'reload'))
gulp.watch([
'css/theme/source/*.{sass,scss}',
'css/theme/source/**/*.{sass,scss}',
'css/theme/template/*.{sass,scss}',
], gulp.series('css-themes', 'reload'))

View File

@@ -256,6 +256,36 @@ export default {
parallaxBackgroundHorizontal: null,
parallaxBackgroundVertical: null,
// Can be used to initialize reveal.js in one of the following views:
// - print: Render the presentation so that it can be printed to PDF
// - scroll: Show the presentation as a tall scrollable page with scroll
// triggered animations
view: null,
// Adjusts the height of each slide in the scroll view.
// - full: Each slide is as tall as the viewport
// - compact: Slides are as small as possible, allowing multiple slides
// to be visible in parallel on tall devices
scrollLayout: 'full',
// Control how scroll snapping works in the scroll view.
// - false: No snapping, scrolling is continuous
// - proximity: Snap when close to a slide
// - mandatory: Always snap to the closest slide
//
// Only applies to presentations in scroll view.
scrollSnap: 'mandatory',
// Enables and configure the scroll view progress bar.
// - 'auto': Show the scrollbar while scrolling, hide while idle
// - true: Always show the scrollbar
// - false: Never show the scrollbar
scrollProgress: 'auto',
// Automatically activate the scroll view when we the viewport falls
// below the given width.
scrollActivationWidth: 435,
// The maximum number of pages a single slide can expand onto when printing
// to PDF, unlimited by default
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
@@ -287,7 +317,7 @@ export default {
// Time before the cursor is hidden (in ms)
hideCursorTime: 5000,
// Should we automatmically sort and set indices for fragments
// Should we automatically sort and set indices for fragments
// at each sync? (See Reveal.sync)
sortFragmentsOnSync: true,

View File

@@ -504,7 +504,7 @@ export default class AutoAnimate {
} );
// Line numbers
this.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-line[data-line-number]', node => {
this.findAutoAnimateMatches( pairs, pair.from, pair.to, '.hljs .hljs-ln-numbers[data-line-number]', node => {
return node.getAttribute( 'data-line-number' );
}, {
scale: false,

View File

@@ -190,10 +190,30 @@ export default class Backgrounds {
if( data.backgroundPosition ) contentElement.style.backgroundPosition = data.backgroundPosition;
if( data.backgroundOpacity ) contentElement.style.opacity = data.backgroundOpacity;
const contrastClass = this.getContrastClass( slide );
if( typeof contrastClass === 'string' ) {
slide.classList.add( contrastClass );
}
}
/**
* Returns a class name that can be applied to a slide to indicate
* if it has a light or dark background.
*
* @param {*} slide
*
* @returns {string|null}
*/
getContrastClass( slide ) {
const element = slide.slideBackgroundElement;
// If this slide has a background color, we add a class that
// signals if it is light or dark. If the slide has no background
// color, no class will be added
let contrastColor = data.backgroundColor;
let contrastColor = slide.getAttribute( 'data-background-color' );
// If no bg color was found, or it cannot be converted by colorToRgb, check the computed background
if( !contrastColor || !colorToRgb( contrastColor ) ) {
@@ -211,14 +231,32 @@ export default class Backgrounds {
// an element with no background
if( rgb && rgb.a !== 0 ) {
if( colorBrightness( contrastColor ) < 128 ) {
slide.classList.add( 'has-dark-background' );
return 'has-dark-background';
}
else {
slide.classList.add( 'has-light-background' );
return 'has-light-background';
}
}
}
return null;
}
/**
* Bubble the 'has-light-background'/'has-dark-background' classes.
*/
bubbleSlideContrastClassToElement( slide, target ) {
[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => {
if( slide.classList.contains( classToBubble ) ) {
target.classList.add( classToBubble );
}
else {
target.classList.remove( classToBubble );
}
}, this );
}
/**
@@ -322,14 +360,7 @@ export default class Backgrounds {
// If there's a background brightness flag for this slide,
// bubble it to the .reveal container
if( currentSlide ) {
[ 'has-light-background', 'has-dark-background' ].forEach( classToBubble => {
if( currentSlide.classList.contains( classToBubble ) ) {
this.Reveal.getRevealElement().classList.add( classToBubble );
}
else {
this.Reveal.getRevealElement().classList.remove( classToBubble );
}
}, this );
this.bubbleSlideContrastClassToElement( currentSlide, this.Reveal.getRevealElement() );
}
// Allow the first background to apply without transition

View File

@@ -174,24 +174,23 @@ export default class Fragments {
*
* @return {{shown: array, hidden: array}}
*/
update( index, fragments ) {
update( index, fragments, slide = this.Reveal.getCurrentSlide() ) {
let changedFragments = {
shown: [],
hidden: []
};
let currentSlide = this.Reveal.getCurrentSlide();
if( currentSlide && this.Reveal.getConfig().fragments ) {
if( slide && this.Reveal.getConfig().fragments ) {
fragments = fragments || this.sort( currentSlide.querySelectorAll( '.fragment' ) );
fragments = fragments || this.sort( slide.querySelectorAll( '.fragment' ) );
if( fragments.length ) {
let maxIndex = 0;
if( typeof index !== 'number' ) {
let currentFragment = this.sort( currentSlide.querySelectorAll( '.fragment.visible' ) ).pop();
let currentFragment = this.sort( slide.querySelectorAll( '.fragment.visible' ) ).pop();
if( currentFragment ) {
index = parseInt( currentFragment.getAttribute( 'data-fragment-index' ) || 0, 10 );
}
@@ -252,7 +251,7 @@ export default class Fragments {
// the current fragment index.
index = typeof index === 'number' ? index : -1;
index = Math.max( Math.min( index, maxIndex ), -1 );
currentSlide.setAttribute( 'data-fragment', index );
slide.setAttribute( 'data-fragment', index );
}

View File

@@ -17,7 +17,6 @@ export default class Keyboard {
this.bindings = {};
this.onDocumentKeyDown = this.onDocumentKeyDown.bind( this );
this.onDocumentKeyPress = this.onDocumentKeyPress.bind( this );
}
@@ -54,7 +53,6 @@ export default class Keyboard {
bind() {
document.addEventListener( 'keydown', this.onDocumentKeyDown, false );
document.addEventListener( 'keypress', this.onDocumentKeyPress, false );
}
@@ -64,7 +62,6 @@ export default class Keyboard {
unbind() {
document.removeEventListener( 'keydown', this.onDocumentKeyDown, false );
document.removeEventListener( 'keypress', this.onDocumentKeyPress, false );
}
@@ -135,20 +132,6 @@ export default class Keyboard {
}
/**
* Handler for the document level 'keypress' event.
*
* @param {object} event
*/
onDocumentKeyPress( event ) {
// Check if the pressed key is question mark
if( event.shiftKey && event.charCode === 63 ) {
this.Reveal.toggleHelp();
}
}
/**
* Handler for the document level 'keydown' event.
*
@@ -184,10 +167,10 @@ export default class Keyboard {
let activeElementIsNotes = document.activeElement && document.activeElement.className && /speaker-notes/i.test( document.activeElement.className);
// Whitelist certain modifiers for slide navigation shortcuts
let isNavigationKey = [32, 37, 38, 39, 40, 78, 80].indexOf( event.keyCode ) !== -1;
let keyCodeUsesModifier = [32, 37, 38, 39, 40, 78, 80, 191].indexOf( event.keyCode ) !== -1;
// Prevent all other events when a modifier is pressed
let unusedModifier = !( isNavigationKey && event.shiftKey || event.altKey ) &&
let unusedModifier = !( keyCodeUsesModifier && event.shiftKey || event.altKey ) &&
( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey );
// Disregard the event if there's a focused element or a
@@ -351,7 +334,7 @@ export default class Keyboard {
}
}
// TWO-SPOT, SEMICOLON, B, V, PERIOD, LOGITECH PRESENTER TOOLS "BLACK SCREEN" BUTTON
else if( keyCode === 58 || keyCode === 59 || keyCode === 66 || keyCode === 86 || keyCode === 190 || keyCode === 191 ) {
else if( [58, 59, 66, 86, 190].includes( keyCode ) || ( keyCode === 191 && !event.shiftKey ) ) {
this.Reveal.togglePause();
}
// F
@@ -360,16 +343,20 @@ export default class Keyboard {
}
// A
else if( keyCode === 65 ) {
if ( config.autoSlideStoppable ) {
if( config.autoSlideStoppable ) {
this.Reveal.toggleAutoSlide( autoSlideWasPaused );
}
}
// G
else if( keyCode === 71 ) {
if ( config.jumpToSlide ) {
if( config.jumpToSlide ) {
this.Reveal.toggleJumpToSlide();
}
}
// ?
else if( keyCode === 191 && event.shiftKey ) {
this.Reveal.toggleHelp();
}
else {
triggered = false;
}

View File

@@ -49,7 +49,7 @@ export default class Location {
// If the first bit is not fully numeric and there is a name we
// can assume that this is a named link
if( !/^[0-9]*$/.test( bits[0] ) && name.length ) {
let element;
let slide;
let f;
@@ -62,12 +62,14 @@ export default class Location {
// Ensure the named link is a valid HTML ID attribute
try {
element = document.getElementById( decodeURIComponent( name ) );
slide = document
.getElementById( decodeURIComponent( name ) )
.closest('.slides section');
}
catch ( error ) { }
if( element ) {
return { ...this.Reveal.getIndices( element ), f };
if( slide ) {
return { ...this.Reveal.getIndices( slide ), f };
}
}
else {

View File

@@ -38,10 +38,12 @@ export default class Notes {
*/
update() {
if( this.Reveal.getConfig().showNotes && this.element && this.Reveal.getCurrentSlide() && !this.Reveal.print.isPrintingPDF() ) {
if( this.Reveal.getConfig().showNotes &&
this.element && this.Reveal.getCurrentSlide() &&
!this.Reveal.isScrollView() &&
!this.Reveal.isPrintView()
) {
this.element.innerHTML = this.getSlideNotes() || '<span class="notes-placeholder">No notes on this slide.</span>';
}
}
@@ -54,7 +56,11 @@ export default class Notes {
*/
updateVisibility() {
if( this.Reveal.getConfig().showNotes && this.hasNotes() && !this.Reveal.print.isPrintingPDF() ) {
if( this.Reveal.getConfig().showNotes &&
this.hasNotes() &&
!this.Reveal.isScrollView() &&
!this.Reveal.isPrintView()
) {
this.Reveal.getRevealElement().classList.add( 'show-notes' );
}
else {

View File

@@ -24,7 +24,7 @@ export default class Overview {
activate() {
// Only proceed if enabled in config
if( this.Reveal.getConfig().overview && !this.isActive() ) {
if( this.Reveal.getConfig().overview && !this.Reveal.isScrollView() && !this.isActive() ) {
this.active = true;

View File

@@ -27,12 +27,10 @@ export default class Pointer {
configure( config, oldConfig ) {
if( config.mouseWheel ) {
document.addEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); // FF
document.addEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
document.addEventListener( 'wheel', this.onDocumentMouseScroll, false );
}
else {
document.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false ); // FF
document.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'wheel', this.onDocumentMouseScroll, false );
}
// Auto-hide the mouse pointer when its inactive
@@ -79,8 +77,7 @@ export default class Pointer {
this.showCursor();
document.removeEventListener( 'DOMMouseScroll', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousewheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'wheel', this.onDocumentMouseScroll, false );
document.removeEventListener( 'mousemove', this.onDocumentCursorActive, false );
document.removeEventListener( 'mousedown', this.onDocumentCursorActive, false );
@@ -126,4 +123,4 @@ export default class Pointer {
}
}
}

View File

@@ -4,7 +4,7 @@ import { queryAll, createStyleSheet } from '../utils/util.js'
/**
* Setups up our presentation for printing/exporting to PDF.
*/
export default class Print {
export default class PrintView {
constructor( Reveal ) {
@@ -16,7 +16,7 @@ export default class Print {
* Configures the presentation for printing to a static
* PDF.
*/
async setupPDF() {
async activate() {
const config = this.Reveal.getConfig();
const slides = queryAll( this.Reveal.getRevealElement(), SLIDES_SELECTOR )
@@ -42,11 +42,11 @@ export default class Print {
// Limit the size of certain elements to the dimensions of the slide
createStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );
document.documentElement.classList.add( 'print-pdf' );
document.documentElement.classList.add( 'reveal-print', 'print-pdf' );
document.body.style.width = pageWidth + 'px';
document.body.style.height = pageHeight + 'px';
const viewportElement = document.querySelector( '.reveal-viewport' );
const viewportElement = this.Reveal.getViewportElement();
let presentationBackground;
if( viewportElement ) {
const viewportStyles = window.getComputedStyle( viewportElement );
@@ -226,12 +226,12 @@ export default class Print {
}
/**
* Checks if this instance is being used to print a PDF.
* Checks if the print mode is/should be activated.
*/
isPrintingPDF() {
isActive() {
return ( /print-pdf/gi ).test( window.location.search );
return this.Reveal.getConfig().view === 'print';
}
}
}

View File

@@ -0,0 +1,888 @@
import { HORIZONTAL_SLIDES_SELECTOR } from '../utils/constants.js'
import { queryAll } from '../utils/util.js'
const HIDE_SCROLLBAR_TIMEOUT = 500;
const MAX_PROGRESS_SPACING = 4;
const MIN_PROGRESS_SEGMENT_HEIGHT = 6;
const MIN_PLAYHEAD_HEIGHT = 8;
/**
* The scroll view lets you read a reveal.js presentation
* as a linear scrollable page.
*/
export default class ScrollView {
constructor( Reveal ) {
this.Reveal = Reveal;
this.active = false;
this.activatedCallbacks = [];
this.onScroll = this.onScroll.bind( this );
}
/**
* Activates the scroll view. This rearranges the presentation DOM
* by—among other things—wrapping each slide in a page element.
*/
activate() {
if( this.active ) return;
const stateBeforeActivation = this.Reveal.getState();
this.active = true;
// Store the full presentation HTML so that we can restore it
// when/if the scroll view is deactivated
this.slideHTMLBeforeActivation = this.Reveal.getSlidesElement().innerHTML;
const horizontalSlides = queryAll( this.Reveal.getRevealElement(), HORIZONTAL_SLIDES_SELECTOR );
this.viewportElement.classList.add( 'loading-scroll-mode', 'reveal-scroll' );
let presentationBackground;
const viewportStyles = window.getComputedStyle( this.viewportElement );
if( viewportStyles && viewportStyles.background ) {
presentationBackground = viewportStyles.background;
}
const pageElements = [];
const pageContainer = horizontalSlides[0].parentNode;
let previousSlide;
// Creates a new page element and appends the given slide/bg
// to it.
const createPageElement = ( slide, h, v ) => {
let contentContainer;
// If this slide is part of an auto-animation sequence, we
// group it under the same page element as the previous slide
if( previousSlide && this.Reveal.shouldAutoAnimateBetween( previousSlide, slide ) ) {
contentContainer = document.createElement( 'div' );
contentContainer.className = 'scroll-page-content scroll-auto-animate-page';
contentContainer.style.display = 'none';
previousSlide.closest( '.scroll-page-content' ).parentNode.appendChild( contentContainer );
}
else {
// Wrap the slide in a page element and hide its overflow
// so that no page ever flows onto another
const page = document.createElement( 'div' );
page.className = 'scroll-page';
pageElements.push( page );
// Copy the presentation-wide background to each page
if( presentationBackground ) {
page.style.background = presentationBackground;
}
const stickyContainer = document.createElement( 'div' );
stickyContainer.className = 'scroll-page-sticky';
page.appendChild( stickyContainer );
contentContainer = document.createElement( 'div' );
contentContainer.className = 'scroll-page-content';
stickyContainer.appendChild( contentContainer );
}
contentContainer.appendChild( slide );
slide.classList.remove( 'past', 'future' );
slide.setAttribute( 'data-index-h', h );
slide.setAttribute( 'data-index-v', v );
if( slide.slideBackgroundElement ) {
slide.slideBackgroundElement.remove( 'past', 'future' );
contentContainer.insertBefore( slide.slideBackgroundElement, slide );
}
previousSlide = slide;
}
// Slide and slide background layout
horizontalSlides.forEach( ( horizontalSlide, h ) => {
if( this.Reveal.isVerticalStack( horizontalSlide ) ) {
horizontalSlide.querySelectorAll( 'section' ).forEach( ( verticalSlide, v ) => {
createPageElement( verticalSlide, h, v );
});
}
else {
createPageElement( horizontalSlide, h, 0 );
}
}, this );
this.createProgressBar();
// Remove leftover stacks
queryAll( this.Reveal.getRevealElement(), '.stack' ).forEach( stack => stack.remove() );
// Add our newly created pages to the DOM
pageElements.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() );
this.Reveal.layout();
this.Reveal.setState( stateBeforeActivation );
this.activatedCallbacks.forEach( callback => callback() );
this.activatedCallbacks = [];
this.restoreScrollPosition();
this.viewportElement.classList.remove( 'loading-scroll-mode' );
this.viewportElement.addEventListener( 'scroll', this.onScroll, { passive: true } );
}
/**
* Deactivates the scroll view and restores the standard slide-based
* presentation.
*/
deactivate() {
if( !this.active ) return;
const stateBeforeDeactivation = this.Reveal.getState();
this.active = false;
this.viewportElement.removeEventListener( 'scroll', this.onScroll );
this.viewportElement.classList.remove( 'reveal-scroll' );
this.removeProgressBar();
this.Reveal.getSlidesElement().innerHTML = this.slideHTMLBeforeActivation;
this.Reveal.sync();
this.Reveal.setState( stateBeforeDeactivation );
this.slideHTMLBeforeActivation = null;
}
toggle( override ) {
if( typeof override === 'boolean' ) {
override ? this.activate() : this.deactivate();
}
else {
this.isActive() ? this.deactivate() : this.activate();
}
}
/**
* Checks if the scroll view is currently active.
*/
isActive() {
return this.active;
}
/**
* Renders the progress bar component.
*/
createProgressBar() {
this.progressBar = document.createElement( 'div' );
this.progressBar.className = 'scrollbar';
this.progressBarInner = document.createElement( 'div' );
this.progressBarInner.className = 'scrollbar-inner';
this.progressBar.appendChild( this.progressBarInner );
this.progressBarPlayhead = document.createElement( 'div' );
this.progressBarPlayhead.className = 'scrollbar-playhead';
this.progressBarInner.appendChild( this.progressBarPlayhead );
this.viewportElement.insertBefore( this.progressBar, this.viewportElement.firstChild );
const handleDocumentMouseMove = ( event ) => {
let progress = ( event.clientY - this.progressBarInner.getBoundingClientRect().top ) / this.progressBarHeight;
progress = Math.max( Math.min( progress, 1 ), 0 );
this.viewportElement.scrollTop = progress * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
};
const handleDocumentMouseUp = ( event ) => {
this.draggingProgressBar = false;
this.showProgressBar();
document.removeEventListener( 'mousemove', handleDocumentMouseMove );
document.removeEventListener( 'mouseup', handleDocumentMouseUp );
};
const handleMouseDown = ( event ) => {
event.preventDefault();
this.draggingProgressBar = true;
document.addEventListener( 'mousemove', handleDocumentMouseMove );
document.addEventListener( 'mouseup', handleDocumentMouseUp );
handleDocumentMouseMove( event );
};
this.progressBarInner.addEventListener( 'mousedown', handleMouseDown );
}
removeProgressBar() {
if( this.progressBar ) {
this.progressBar.remove();
this.progressBar = null;
}
}
layout() {
if( this.isActive() ) {
this.syncPages();
this.syncScrollPosition();
}
}
/**
* Updates our pages to match the latest configuration and
* presentation size.
*/
syncPages() {
const config = this.Reveal.getConfig();
const slideSize = this.Reveal.getComputedSlideSize( window.innerWidth, window.innerHeight );
const scale = this.Reveal.getScale();
const useCompactLayout = config.scrollLayout === 'compact';
const viewportHeight = this.viewportElement.offsetHeight;
const compactHeight = slideSize.height * scale;
const pageHeight = useCompactLayout ? compactHeight : viewportHeight;
// The height that needs to be scrolled between scroll triggers
const scrollTriggerHeight = useCompactLayout ? compactHeight : viewportHeight;
this.viewportElement.style.setProperty( '--page-height', pageHeight + 'px' );
this.viewportElement.style.scrollSnapType = typeof config.scrollSnap === 'string' ? `y ${config.scrollSnap}` : '';
// This will hold all scroll triggers used to show/hide slides
this.slideTriggers = [];
const pageElements = Array.from( this.Reveal.getRevealElement().querySelectorAll( '.scroll-page' ) );
this.pages = pageElements.map( pageElement => {
const page = this.createPage({
pageElement,
slideElement: pageElement.querySelector( 'section' ),
stickyElement: pageElement.querySelector( '.scroll-page-sticky' ),
contentElement: pageElement.querySelector( '.scroll-page-content' ),
backgroundElement: pageElement.querySelector( '.slide-background' ),
autoAnimateElements: pageElement.querySelectorAll( '.scroll-auto-animate-page' ),
autoAnimatePages: []
});
page.pageElement.style.setProperty( '--slide-height', config.center === true ? 'auto' : slideSize.height + 'px' );
this.slideTriggers.push({
page: page,
activate: () => this.activatePage( page ),
deactivate: () => this.deactivatePage( page )
});
// Create scroll triggers that show/hide fragments
this.createFragmentTriggersForPage( page );
// Create scroll triggers for triggering auto-animate steps
if( page.autoAnimateElements.length > 0 ) {
this.createAutoAnimateTriggersForPage( page );
}
let totalScrollTriggerCount = Math.max( page.scrollTriggers.length - 1, 0 );
// Each auto-animate step may include its own scroll triggers
// for fragments, ensure we count those as well
totalScrollTriggerCount += page.autoAnimatePages.reduce( ( total, page ) => {
return total + Math.max( page.scrollTriggers.length - 1, 0 );
}, page.autoAnimatePages.length );
// Clean up from previous renders
page.pageElement.querySelectorAll( '.scroll-snap-point' ).forEach( el => el.remove() );
// Create snap points for all scroll triggers
// - Can't be absolute in FF
// - Can't be 0-height in Safari
// - Can't use snap-align on parent in Safari because then
// inner triggers won't work
for( let i = 0; i < totalScrollTriggerCount + 1; i++ ) {
const triggerStick = document.createElement( 'div' );
triggerStick.className = 'scroll-snap-point';
triggerStick.style.height = scrollTriggerHeight + 'px';
triggerStick.style.scrollSnapAlign = useCompactLayout ? 'center' : 'start';
page.pageElement.appendChild( triggerStick );
if( i === 0 ) {
triggerStick.style.marginTop = -scrollTriggerHeight + 'px';
}
}
// In the compact layout, only slides with scroll triggers cover the
// full viewport height. This helps avoid empty gaps before or after
// a sticky slide.
if( useCompactLayout && page.scrollTriggers.length > 0 ) {
page.pageHeight = viewportHeight;
page.pageElement.style.setProperty( '--page-height', viewportHeight + 'px' );
}
else {
page.pageHeight = pageHeight;
page.pageElement.style.removeProperty( '--page-height' );
}
// Add scroll padding based on how many scroll triggers we have
page.scrollPadding = scrollTriggerHeight * totalScrollTriggerCount;
// The total height including scrollable space
page.totalHeight = page.pageHeight + page.scrollPadding;
// This is used to pad the height of our page in CSS
page.pageElement.style.setProperty( '--page-scroll-padding', page.scrollPadding + 'px' );
// If this is a sticky page, stick it to the vertical center
if( totalScrollTriggerCount > 0 ) {
page.stickyElement.style.position = 'sticky';
page.stickyElement.style.top = Math.max( ( viewportHeight - page.pageHeight ) / 2, 0 ) + 'px';
}
else {
page.stickyElement.style.position = 'relative';
page.pageElement.style.scrollSnapAlign = page.pageHeight < viewportHeight ? 'center' : 'start';
}
return page;
} );
this.setTriggerRanges();
/*
console.log(this.slideTriggers.map( t => {
return {
range: `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`,
triggers: t.page.scrollTriggers.map( t => {
return `${t.range[0].toFixed(2)}-${t.range[1].toFixed(2)}`
}).join( ', ' ),
}
}))
*/
this.viewportElement.setAttribute( 'data-scrollbar', config.scrollProgress );
if( config.scrollProgress && this.totalScrollTriggerCount > 1 ) {
// Create the progress bar if it doesn't already exist
if( !this.progressBar ) this.createProgressBar();
this.syncProgressBar();
}
else {
this.removeProgressBar();
}
}
/**
* Calculates and sets the scroll range for all of our scroll
* triggers.
*/
setTriggerRanges() {
// Calculate the total number of scroll triggers
this.totalScrollTriggerCount = this.slideTriggers.reduce( ( total, trigger ) => {
return total + Math.max( trigger.page.scrollTriggers.length, 1 );
}, 0 );
let rangeStart = 0;
// Calculate the scroll range of each scroll trigger on a scale
// of 0-1
this.slideTriggers.forEach( ( trigger, i ) => {
trigger.range = [
rangeStart,
rangeStart + Math.max( trigger.page.scrollTriggers.length, 1 ) / this.totalScrollTriggerCount
];
const scrollTriggerSegmentSize = ( trigger.range[1] - trigger.range[0] ) / trigger.page.scrollTriggers.length;
// Set the range for each inner scroll trigger
trigger.page.scrollTriggers.forEach( ( scrollTrigger, i ) => {
scrollTrigger.range = [
rangeStart + i * scrollTriggerSegmentSize,
rangeStart + ( i + 1 ) * scrollTriggerSegmentSize
];
} );
rangeStart = trigger.range[1];
} );
}
/**
* Creates one scroll trigger for each fragments in the given page.
*
* @param {*} page
*/
createFragmentTriggersForPage( page, slideElement ) {
slideElement = slideElement || page.slideElement;
// Each fragment 'group' is an array containing one or more
// fragments. Multiple fragments that appear at the same time
// are part of the same group.
const fragmentGroups = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment' ), true );
// Create scroll triggers that show/hide fragments
if( fragmentGroups.length ) {
page.fragments = this.Reveal.fragments.sort( slideElement.querySelectorAll( '.fragment:not(.disabled)' ) );
page.scrollTriggers.push(
// Trigger for the initial state with no fragments visible
{
activate: () => {
this.Reveal.fragments.update( -1, page.fragments, slideElement );
}
},
// Triggers for each fragment group
...fragmentGroups.map( ( fragments, i ) => ({
activate: () => {
this.Reveal.fragments.update( i, page.fragments, slideElement );
}
})
)
);
}
return page.scrollTriggers.length;
}
/**
* Creates scroll triggers for the auto-animate steps in the
* given page.
*
* @param {*} page
*/
createAutoAnimateTriggersForPage( page ) {
if( page.autoAnimateElements.length > 0 ) {
// Triggers for each subsequent auto-animate slide
this.slideTriggers.push( ...Array.from( page.autoAnimateElements ).map( ( autoAnimateElement, i ) => {
let autoAnimatePage = this.createPage({
slideElement: autoAnimateElement.querySelector( 'section' ),
contentElement: autoAnimateElement,
backgroundElement: autoAnimateElement.querySelector( '.slide-background' )
});
// Create fragment scroll triggers for the auto-animate slide
this.createFragmentTriggersForPage( autoAnimatePage, autoAnimatePage.slideElement );
page.autoAnimatePages.push( autoAnimatePage );
// Return our slide trigger
return {
page: autoAnimatePage,
activate: () => this.activatePage( autoAnimatePage ),
deactivate: () => this.deactivatePage( autoAnimatePage )
};
}));
}
}
/**
* Helper method for creating a page definition and adding
* required fields. A "page" is a slide or auto-animate step.
*/
createPage( page ) {
page.scrollTriggers = [];
page.indexh = parseInt( page.slideElement.getAttribute( 'data-index-h' ), 10 );
page.indexv = parseInt( page.slideElement.getAttribute( 'data-index-v' ), 10 );
return page;
}
/**
* Rerenders progress bar segments so that they match the current
* reveal.js config and size.
*/
syncProgressBar() {
this.progressBarInner.querySelectorAll( '.scrollbar-slide' ).forEach( slide => slide.remove() );
const scrollHeight = this.viewportElement.scrollHeight;
const viewportHeight = this.viewportElement.offsetHeight;
const viewportHeightFactor = viewportHeight / scrollHeight;
this.progressBarHeight = this.progressBarInner.offsetHeight;
this.playheadHeight = Math.max( viewportHeightFactor * this.progressBarHeight, MIN_PLAYHEAD_HEIGHT );
this.progressBarScrollableHeight = this.progressBarHeight - this.playheadHeight;
const progressSegmentHeight = viewportHeight / scrollHeight * this.progressBarHeight;
const spacing = Math.min( progressSegmentHeight / 8, MAX_PROGRESS_SPACING );
this.progressBarPlayhead.style.height = this.playheadHeight - spacing + 'px';
// Don't show individual segments if they're too small
if( progressSegmentHeight > MIN_PROGRESS_SEGMENT_HEIGHT ) {
this.slideTriggers.forEach( slideTrigger => {
const { page } = slideTrigger;
// Visual representation of a slide
page.progressBarSlide = document.createElement( 'div' );
page.progressBarSlide.className = 'scrollbar-slide';
page.progressBarSlide.style.top = slideTrigger.range[0] * this.progressBarHeight + 'px';
page.progressBarSlide.style.height = ( slideTrigger.range[1] - slideTrigger.range[0] ) * this.progressBarHeight - spacing + 'px';
page.progressBarSlide.classList.toggle( 'has-triggers', page.scrollTriggers.length > 0 );
this.progressBarInner.appendChild( page.progressBarSlide );
// Visual representations of each scroll trigger
page.scrollTriggerElements = page.scrollTriggers.map( ( trigger, i ) => {
const triggerElement = document.createElement( 'div' );
triggerElement.className = 'scrollbar-trigger';
triggerElement.style.top = ( trigger.range[0] - slideTrigger.range[0] ) * this.progressBarHeight + 'px';
triggerElement.style.height = ( trigger.range[1] - trigger.range[0] ) * this.progressBarHeight - spacing + 'px';
page.progressBarSlide.appendChild( triggerElement );
if( i === 0 ) triggerElement.style.display = 'none';
return triggerElement;
} );
} );
}
else {
this.pages.forEach( page => page.progressBarSlide = null );
}
}
/**
* Reads the current scroll position and updates our active
* trigger states accordingly.
*/
syncScrollPosition() {
const viewportHeight = this.viewportElement.offsetHeight;
const viewportHeightFactor = viewportHeight / this.viewportElement.scrollHeight;
const scrollTop = this.viewportElement.scrollTop;
const scrollHeight = this.viewportElement.scrollHeight - viewportHeight
const scrollProgress = Math.max( Math.min( scrollTop / scrollHeight, 1 ), 0 );
const scrollProgressMid = Math.max( Math.min( ( scrollTop + viewportHeight / 2 ) / this.viewportElement.scrollHeight, 1 ), 0 );
let activePage;
this.slideTriggers.forEach( ( trigger ) => {
const { page } = trigger;
const shouldPreload = scrollProgress >= trigger.range[0] - viewportHeightFactor*2 &&
scrollProgress <= trigger.range[1] + viewportHeightFactor*2;
// Load slides that are within the preload range
if( shouldPreload && !page.loaded ) {
page.loaded = true;
this.Reveal.slideContent.load( page.slideElement );
}
else if( page.loaded ) {
page.loaded = false;
this.Reveal.slideContent.unload( page.slideElement );
}
// If we're within this trigger range, activate it
if( scrollProgress >= trigger.range[0] && scrollProgress <= trigger.range[1] ) {
this.activateTrigger( trigger );
activePage = trigger.page;
}
// .. otherwise deactivate
else if( trigger.active ) {
this.deactivateTrigger( trigger );
}
} );
// Each page can have its own scroll triggers, check if any of those
// need to be activated/deactivated
if( activePage ) {
activePage.scrollTriggers.forEach( ( trigger ) => {
if( scrollProgressMid >= trigger.range[0] && scrollProgressMid <= trigger.range[1] ) {
this.activateTrigger( trigger );
}
else if( trigger.active ) {
this.deactivateTrigger( trigger );
}
} );
}
// Update our visual progress indication
this.setProgressBarValue( scrollTop / ( this.viewportElement.scrollHeight - viewportHeight ) );
}
/**
* Moves the progress bar playhead to the specified position.
*
* @param {number} progress 0-1
*/
setProgressBarValue( progress ) {
if( this.progressBar ) {
this.progressBarPlayhead.style.transform = `translateY(${progress * this.progressBarScrollableHeight}px)`;
this.getAllPages()
.filter( page => page.progressBarSlide )
.forEach( ( page ) => {
page.progressBarSlide.classList.toggle( 'active', page.active === true );
page.scrollTriggers.forEach( ( trigger, i ) => {
page.scrollTriggerElements[i].classList.toggle( 'active', page.active === true && trigger.active === true );
} );
} );
this.showProgressBar();
}
}
/**
* Show the progress bar and, if configured, automatically hide
* it after a delay.
*/
showProgressBar() {
this.progressBar.classList.add( 'visible' );
clearTimeout( this.hideProgressBarTimeout );
if( this.Reveal.getConfig().scrollProgress === 'auto' && !this.draggingProgressBar ) {
this.hideProgressBarTimeout = setTimeout( () => {
if( this.progressBar ) {
this.progressBar.classList.remove( 'visible' );
}
}, HIDE_SCROLLBAR_TIMEOUT );
}
}
/**
* Scrolls the given slide element into view.
*
* @param {HTMLElement} slideElement
*/
scrollToSlide( slideElement ) {
// If the scroll view isn't active yet, queue this action
if( !this.active ) {
this.activatedCallbacks.push( () => this.scrollToSlide( slideElement ) );
}
else {
// Find the trigger for this slide
const trigger = this.getScrollTriggerBySlide( slideElement );
if( trigger ) {
// Use the trigger's range to calculate the scroll position
this.viewportElement.scrollTop = trigger.range[0] * ( this.viewportElement.scrollHeight - this.viewportElement.offsetHeight );
}
}
}
/**
* Persists the current scroll position to session storage
* so that it can be restored.
*/
storeScrollPosition() {
clearTimeout( this.storeScrollPositionTimeout );
this.storeScrollPositionTimeout = setTimeout( () => {
sessionStorage.setItem( 'reveal-scroll-top', this.viewportElement.scrollTop );
sessionStorage.setItem( 'reveal-scroll-origin', location.origin + location.pathname );
this.storeScrollPositionTimeout = null;
}, 50 );
}
/**
* Restores the scroll position when a deck is reloader.
*/
restoreScrollPosition() {
const scrollPosition = sessionStorage.getItem( 'reveal-scroll-top' );
const scrollOrigin = sessionStorage.getItem( 'reveal-scroll-origin' );
if( scrollPosition && scrollOrigin === location.origin + location.pathname ) {
this.viewportElement.scrollTop = parseInt( scrollPosition, 10 );
}
}
/**
* Activates the given page and starts its embedded conten
* if there is any.
*
* @param {object} page
*/
activatePage( page ) {
if( !page.active ) {
page.active = true;
const { slideElement, backgroundElement, contentElement, indexh, indexv } = page;
contentElement.style.display = 'block';
slideElement.classList.add( 'present' );
if( backgroundElement ) {
backgroundElement.classList.add( 'present' );
}
this.Reveal.setCurrentScrollPage( slideElement, indexh, indexv );
this.Reveal.backgrounds.bubbleSlideContrastClassToElement( slideElement, this.viewportElement );
// If this page is part of an auto-animation there will be one
// content element per auto-animated page. We need to show the
// current page and hide all others.
Array.from( contentElement.parentNode.querySelectorAll( '.scroll-page-content' ) ).forEach( sibling => {
if( sibling !== contentElement ) {
sibling.style.display = 'none';
}
});
}
}
/**
* Deactivates the page after it has been visible.
*
* @param {object} page
*/
deactivatePage( page ) {
if( page.active ) {
page.active = false;
page.slideElement.classList.remove( 'present' );
page.backgroundElement.classList.remove( 'present' );
}
}
activateTrigger( trigger ) {
if( !trigger.active ) {
trigger.active = true;
trigger.activate();
}
}
deactivateTrigger( trigger ) {
if( trigger.active ) {
trigger.active = false;
if( trigger.deactivate ) {
trigger.deactivate();
}
}
}
/**
* Retrieve a slide by its original h/v index (i.e. the indices the
* slide had before being linearized).
*
* @param {number} h
* @param {number} v
* @returns {HTMLElement}
*/
getSlideByIndices( h, v ) {
const page = this.getAllPages().find( page => {
return page.indexh === h && page.indexv === v;
} );
return page ? page.slideElement : null;
}
/**
* Retrieve a list of all scroll triggers for the given slide
* DOM element.
*
* @param {HTMLElement} slide
* @returns {Array}
*/
getScrollTriggerBySlide( slide ) {
return this.slideTriggers.find( trigger => trigger.page.slideElement === slide );
}
/**
* Get a list of all pages in the scroll view. This includes
* both top-level slides and auto-animate steps.
*
* @returns {Array}
*/
getAllPages() {
return this.pages.flatMap( page => [page, ...(page.autoAnimatePages || [])] );
}
onScroll() {
this.syncScrollPosition();
this.storeScrollPosition();
}
get viewportElement() {
return this.Reveal.getViewportElement();
}
}

View File

@@ -25,6 +25,10 @@ export default class SlideContent {
*/
shouldPreload( element ) {
if( this.Reveal.isScrollView() ) {
return true;
}
// Prefer an explicit global preload setting
let preload = this.Reveal.getConfig().preloadIframes;

View File

@@ -23,7 +23,7 @@ export default class SlideNumber {
configure( config, oldConfig ) {
let slideNumberDisplay = 'none';
if( config.slideNumber && !this.Reveal.isPrintingPDF() ) {
if( config.slideNumber && !this.Reveal.isPrintView() ) {
if( config.showSlideNumber === 'all' ) {
slideNumberDisplay = 'block';
}

View File

@@ -3,6 +3,8 @@ import SlideNumber from './controllers/slidenumber.js'
import JumpToSlide from './controllers/jumptoslide.js'
import Backgrounds from './controllers/backgrounds.js'
import AutoAnimate from './controllers/autoanimate.js'
import ScrollView from './controllers/scrollview.js'
import PrintView from './controllers/printview.js'
import Fragments from './controllers/fragments.js'
import Overview from './controllers/overview.js'
import Keyboard from './controllers/keyboard.js'
@@ -11,7 +13,6 @@ import Controls from './controllers/controls.js'
import Progress from './controllers/progress.js'
import Pointer from './controllers/pointer.js'
import Plugins from './controllers/plugins.js'
import Print from './controllers/print.js'
import Touch from './controllers/touch.js'
import Focus from './controllers/focus.js'
import Notes from './controllers/notes.js'
@@ -27,7 +28,7 @@ import {
} from './utils/constants.js'
// The reveal.js version
export const VERSION = '4.5.0';
export const VERSION = '5.0.0';
/**
* reveal.js
@@ -105,6 +106,8 @@ export default function( revealElement, options ) {
jumpToSlide = new JumpToSlide( Reveal ),
autoAnimate = new AutoAnimate( Reveal ),
backgrounds = new Backgrounds( Reveal ),
scrollView = new ScrollView( Reveal ),
printView = new PrintView( Reveal ),
fragments = new Fragments( Reveal ),
overview = new Overview( Reveal ),
keyboard = new Keyboard( Reveal ),
@@ -113,7 +116,6 @@ export default function( revealElement, options ) {
progress = new Progress( Reveal ),
pointer = new Pointer( Reveal ),
plugins = new Plugins( Reveal ),
print = new Print( Reveal ),
focus = new Focus( Reveal ),
touch = new Touch( Reveal ),
notes = new Notes( Reveal );
@@ -140,6 +142,11 @@ export default function( revealElement, options ) {
// 5. Query params
config = { ...defaultConfig, ...config, ...options, ...initOptions, ...Util.getQueryHash() };
// Legacy support for the ?print-pdf query
if( /print-pdf/gi.test( window.location.search ) ) {
config.view = 'print';
}
setViewport();
// Force a layout when the whole page, incl fonts, has loaded
@@ -201,12 +208,15 @@ export default function( revealElement, options ) {
// Updates the presentation to match the current configuration values
configure();
// Read the initial hash
location.readURL();
// Create slide backgrounds
backgrounds.update( true );
// Activate the print/scroll view if configured
activateInitialView();
// Read the initial hash
location.readURL();
// Notify listeners that the presentation is ready but use a 1ms
// timeout to ensure it's not fired synchronously after #initialize()
setTimeout( () => {
@@ -225,19 +235,41 @@ export default function( revealElement, options ) {
});
}, 1 );
// Special setup and config is required when printing to PDF
if( print.isPrintingPDF() ) {
removeEventListeners();
}
// The document needs to have loaded for the PDF layout
// measurements to be accurate
if( document.readyState === 'complete' ) {
print.setupPDF();
/**
* Activates the correct reveal.js view based on our config.
* This is only invoked once during initialization.
*/
function activateInitialView() {
const activatePrintView = config.view === 'print';
const activateScrollView = config.view === 'scroll' || config.view === 'reader';
if( activatePrintView || activateScrollView ) {
if( activatePrintView ) {
removeEventListeners();
}
else {
window.addEventListener( 'load', () => {
print.setupPDF();
} );
touch.unbind();
}
// Avoid content flickering during layout
dom.viewport.classList.add( 'loading-scroll-mode' );
if( activatePrintView ) {
// The document needs to have loaded for the PDF layout
// measurements to be accurate
if( document.readyState === 'complete' ) {
printView.activate();
}
else {
window.addEventListener( 'load', () => printView.activate() );
}
}
else {
scrollView.activate();
}
}
@@ -255,7 +287,18 @@ export default function( revealElement, options ) {
if( !config.showHiddenSlides ) {
Util.queryAll( dom.wrapper, 'section[data-visibility="hidden"]' ).forEach( slide => {
slide.parentNode.removeChild( slide );
const parent = slide.parentNode;
// If this slide is part of a stack and that stack will be
// empty after removing the hidden slide, remove the entire
// stack
if( parent.childElementCount === 1 && /section/i.test( parent.nodeName ) ) {
parent.remove();
}
else {
slide.remove();
}
} );
}
@@ -374,7 +417,7 @@ export default function( revealElement, options ) {
function setupScrollPrevention() {
setInterval( () => {
if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
if( !scrollView.isActive() && dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
dom.wrapper.scrollTop = 0;
dom.wrapper.scrollLeft = 0;
}
@@ -441,8 +484,8 @@ export default function( revealElement, options ) {
dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
// Expose our configured slide dimensions as custom props
dom.viewport.style.setProperty( '--slide-width', config.width + 'px' );
dom.viewport.style.setProperty( '--slide-height', config.height + 'px' );
dom.viewport.style.setProperty( '--slide-width', typeof config.width === 'string' ? config.width : config.width + 'px' );
dom.viewport.style.setProperty( '--slide-height', typeof config.height === 'string' ? config.height : config.height + 'px' );
if( config.shuffle ) {
shuffle();
@@ -678,6 +721,26 @@ export default function( revealElement, options ) {
}
/**
* Dispatches a slidechanged event.
*
* @param {string} origin Used to identify multiplex clients
*/
function dispatchSlideChanged( origin ) {
dispatchEvent({
type: 'slidechanged',
data: {
indexh,
indexv,
previousSlide,
currentSlide,
origin
}
});
}
/**
* Dispatched a postMessage of the given type from our window.
*/
@@ -861,7 +924,10 @@ export default function( revealElement, options ) {
*/
function layout() {
if( dom.wrapper && !print.isPrintingPDF() ) {
if( dom.wrapper && !printView.isActive() ) {
const viewportWidth = dom.viewport.offsetWidth;
const viewportHeight = dom.viewport.offsetHeight;
if( !config.disableLayout ) {
@@ -875,7 +941,9 @@ export default function( revealElement, options ) {
document.documentElement.style.setProperty( '--vh', ( window.innerHeight * 0.01 ) + 'px' );
}
const size = getComputedSlideSize();
const size = scrollView.isActive() ?
getComputedSlideSize( viewportWidth, viewportHeight ) :
getComputedSlideSize();
const oldScale = scale;
@@ -892,8 +960,9 @@ export default function( revealElement, options ) {
scale = Math.max( scale, config.minScale );
scale = Math.min( scale, config.maxScale );
// Don't apply any scaling styles if scale is 1
if( scale === 1 ) {
// Don't apply any scaling styles if scale is 1 or we're
// in the scroll view
if( scale === 1 || scrollView.isActive() ) {
dom.slides.style.zoom = '';
dom.slides.style.left = '';
dom.slides.style.top = '';
@@ -921,7 +990,7 @@ export default function( revealElement, options ) {
continue;
}
if( config.center || slide.classList.contains( 'center' ) ) {
if( ( config.center || slide.classList.contains( 'center' ) ) ) {
// Vertical stacks are not centred since their section
// children will be
if( slide.classList.contains( 'stack' ) ) {
@@ -947,9 +1016,25 @@ export default function( revealElement, options ) {
}
});
}
// Responsively turn on the scroll mode if there is an activation
// width configured. Ignore if we're configured to always be in
// scroll mode.
if( typeof config.scrollActivationWidth === 'number' && config.view !== 'scroll' ) {
if( size.presentationWidth > 0 && size.presentationWidth <= config.scrollActivationWidth ) {
if( !scrollView.isActive() ) scrollView.activate();
}
else {
if( scrollView.isActive() ) scrollView.deactivate();
}
}
}
dom.viewport.style.setProperty( '--slide-scale', scale );
dom.viewport.style.setProperty( '--viewport-width', viewportWidth + 'px' );
dom.viewport.style.setProperty( '--viewport-height', viewportHeight + 'px' );
scrollView.layout();
progress.update();
backgrounds.updateParallax();
@@ -970,7 +1055,6 @@ export default function( revealElement, options ) {
* @param {string|number} height
*/
function layoutSlideContents( width, height ) {
// Handle sizing of elements with the 'r-stretch' class
Util.queryAll( dom.slides, 'section > .stretch, section > .r-stretch' ).forEach( element => {
@@ -1006,6 +1090,7 @@ export default function( revealElement, options ) {
* @param {number} [presentationHeight=dom.wrapper.offsetHeight]
*/
function getComputedSlideSize( presentationWidth, presentationHeight ) {
let width = config.width;
let height = config.height;
@@ -1092,6 +1177,19 @@ export default function( revealElement, options ) {
}
/**
* Checks if the current or specified slide is a stack containing
* vertical slides.
*
* @param {HTMLElement} [slide=currentSlide]
* @return {Boolean}
*/
function isVerticalStack( slide = currentSlide ) {
return slide.classList.contains( '.stack' ) || slide.querySelector( 'section' ) !== null;
}
/**
* Returns true if we're on the last slide in the current
* vertical stack.
@@ -1277,6 +1375,14 @@ export default function( revealElement, options ) {
// Query all horizontal slides in the deck
const horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
// If we're in scroll mode, we scroll the target slide into view
// instead of running our standard slide transition
if( scrollView.isActive() ) {
const scrollToSlide = scrollView.getSlideByIndices( h, v );
if( scrollToSlide ) scrollView.scrollToSlide( scrollToSlide );
return;
}
// Abort if there are no slides
if( horizontalSlides.length === 0 ) return;
@@ -1323,6 +1429,9 @@ export default function( revealElement, options ) {
// Detect if we're moving between two auto-animated slides
if( slideChanged && previousSlide && currentSlide && !overview.isActive() ) {
transition = 'running';
autoAnimateTransition = shouldAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexvBefore );
// If this is an auto-animated transition, we disable the
// regular slide transition
@@ -1330,16 +1439,9 @@ export default function( revealElement, options ) {
// Note 20-03-2020:
// This needs to happen before we update slide visibility,
// otherwise transitions will still run in Safari.
if( previousSlide.hasAttribute( 'data-auto-animate' ) && currentSlide.hasAttribute( 'data-auto-animate' )
&& previousSlide.getAttribute( 'data-auto-animate-id' ) === currentSlide.getAttribute( 'data-auto-animate-id' )
&& !( ( indexh > indexhBefore || indexv > indexvBefore ) ? currentSlide : previousSlide ).hasAttribute( 'data-auto-animate-restart' ) ) {
autoAnimateTransition = true;
dom.slides.classList.add( 'disable-slide-transitions' );
if( autoAnimateTransition ) {
dom.slides.classList.add( 'disable-slide-transitions' )
}
transition = 'running';
}
// Update the visibility of slides now that the indices have changed
@@ -1398,16 +1500,7 @@ export default function( revealElement, options ) {
}
if( slideChanged ) {
dispatchEvent({
type: 'slidechanged',
data: {
indexh,
indexv,
previousSlide,
currentSlide,
origin
}
});
dispatchSlideChanged( origin );
}
// Handle embedded content
@@ -1452,6 +1545,71 @@ export default function( revealElement, options ) {
}
/**
* Checks whether or not an auto-animation should take place between
* the two given slides.
*
* @param {HTMLElement} fromSlide
* @param {HTMLElement} toSlide
* @param {number} indexhBefore
* @param {number} indexvBefore
*
* @returns {boolean}
*/
function shouldAutoAnimateBetween( fromSlide, toSlide, indexhBefore, indexvBefore ) {
return fromSlide.hasAttribute( 'data-auto-animate' ) && toSlide.hasAttribute( 'data-auto-animate' ) &&
fromSlide.getAttribute( 'data-auto-animate-id' ) === toSlide.getAttribute( 'data-auto-animate-id' ) &&
!( ( indexh > indexhBefore || indexv > indexvBefore ) ? toSlide : fromSlide ).hasAttribute( 'data-auto-animate-restart' );
}
/**
* Called anytime a new slide should be activated while in the scroll
* view. The active slide is the page that occupies the most space in
* the scrollable viewport.
*
* @param {number} pageIndex
* @param {HTMLElement} slideElement
*/
function setCurrentScrollPage( slideElement, h, v ) {
let indexhBefore = indexh || 0;
indexh = h;
indexv = v;
const slideChanged = currentSlide !== slideElement;
previousSlide = currentSlide;
currentSlide = slideElement;
if( currentSlide && previousSlide ) {
if( config.autoAnimate && shouldAutoAnimateBetween( previousSlide, currentSlide, indexhBefore, indexv ) ) {
// Run the auto-animation between our slides
autoAnimate.run( previousSlide, currentSlide );
}
}
// Start or stop embedded content like videos and iframes
if( slideChanged ) {
if( previousSlide ) {
slideContent.stopEmbeddedContent( previousSlide );
slideContent.stopEmbeddedContent( previousSlide.slideBackgroundElement );
}
slideContent.startEmbeddedContent( currentSlide );
slideContent.startEmbeddedContent( currentSlide.slideBackgroundElement );
}
requestAnimationFrame( () => {
announceStatus( getStatusText( currentSlide ) );
});
dispatchSlideChanged();
}
/**
* Syncs the presentation with the current DOM. Useful
* when new slides or control elements are added or when
@@ -1597,7 +1755,7 @@ export default function( revealElement, options ) {
let slides = Util.queryAll( dom.wrapper, selector ),
slidesLength = slides.length;
let printMode = print.isPrintingPDF();
let printMode = scrollView.isActive() || printView.isActive();
let loopedForwards = false;
let loopedBackwards = false;
@@ -1757,7 +1915,7 @@ export default function( revealElement, options ) {
}
// All slides need to be visible when exporting to PDF
if( print.isPrintingPDF() ) {
if( printView.isActive() ) {
viewDistance = Number.MAX_VALUE;
}
@@ -1988,21 +2146,31 @@ export default function( revealElement, options ) {
// If a slide is specified, return the indices of that slide
if( slide ) {
let isVertical = isVerticalSlide( slide );
let slideh = isVertical ? slide.parentNode : slide;
// In scroll mode the original h/x index is stored on the slide
if( scrollView.isActive() ) {
h = parseInt( slide.getAttribute( 'data-index-h' ), 10 );
// Select all horizontal slides
let horizontalSlides = getHorizontalSlides();
if( slide.getAttribute( 'data-index-v' ) ) {
v = parseInt( slide.getAttribute( 'data-index-v' ), 10 );
}
}
else {
let isVertical = isVerticalSlide( slide );
let slideh = isVertical ? slide.parentNode : slide;
// Now that we know which the horizontal slide is, get its index
h = Math.max( horizontalSlides.indexOf( slideh ), 0 );
// Select all horizontal slides
let horizontalSlides = getHorizontalSlides();
// Assume we're not vertical
v = undefined;
// Now that we know which the horizontal slide is, get its index
h = Math.max( horizontalSlides.indexOf( slideh ), 0 );
// If this is a vertical slide, grab the vertical index
if( isVertical ) {
v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
// Assume we're not vertical
v = undefined;
// If this is a vertical slide, grab the vertical index
if( isVertical ) {
v = Math.max( Util.queryAll( slide.parentNode, 'section' ).indexOf( slide ), 0 );
}
}
}
@@ -2203,11 +2371,7 @@ export default function( revealElement, options ) {
if( currentSlide && config.autoSlide !== false ) {
let fragment = currentSlide.querySelector( '.current-fragment' );
// When the slide first appears there is no "current" fragment so
// we look for a data-autoslide timing on the first fragment
if( !fragment ) fragment = currentSlide.querySelector( '.fragment' );
let fragment = currentSlide.querySelector( '.current-fragment[data-autoslide]' );
let fragmentAutoSlide = fragment ? fragment.getAttribute( 'data-autoslide' ) : null;
let parentAutoSlide = currentSlide.parentNode ? currentSlide.parentNode.getAttribute( 'data-autoslide' ) : null;
@@ -2679,6 +2843,9 @@ export default function( revealElement, options ) {
// Toggles the overview mode on/off
toggleOverview: overview.toggle.bind( overview ),
// Toggles the scroll view on/off
toggleScrollView: scrollView.toggle.bind( scrollView ),
// Toggles the "black screen" mode on/off
togglePause,
@@ -2693,6 +2860,7 @@ export default function( revealElement, options ) {
isLastSlide,
isLastVerticalSlide,
isVerticalSlide,
isVerticalStack,
// State checks
isPaused,
@@ -2700,7 +2868,9 @@ export default function( revealElement, options ) {
isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
isOverview: overview.isActive.bind( overview ),
isFocused: focus.isFocused.bind( focus ),
isPrintingPDF: print.isPrintingPDF.bind( print ),
isScrollView: scrollView.isActive.bind( scrollView ),
isPrintView: printView.isActive.bind( printView ),
// Checks if reveal.js has been loaded and is ready for use
isReady: () => ready,
@@ -2709,6 +2879,10 @@ export default function( revealElement, options ) {
loadSlide: slideContent.load.bind( slideContent ),
unloadSlide: slideContent.unload.bind( slideContent ),
// Media playback
startEmbeddedContent: () => slideContent.startEmbeddedContent( currentSlide ),
stopEmbeddedContent: () => slideContent.stopEmbeddedContent( currentSlide, { unloadIframes: false } ),
// Preview management
showPreview,
hidePreview: closeOverlay,
@@ -2769,6 +2943,8 @@ export default function( revealElement, options ) {
hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,
hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,
shouldAutoAnimateBetween,
// Adds/removes a custom key binding
addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),
@@ -2780,6 +2956,7 @@ export default function( revealElement, options ) {
registerKeyboardShortcut: keyboard.registerKeyboardShortcut.bind( keyboard ),
getComputedSlideSize,
setCurrentScrollPage,
// Returns the current scale of the presentation content
getScale: () => scale,
@@ -2816,13 +2993,14 @@ export default function( revealElement, options ) {
getStatusText,
// Controllers
print,
focus,
scroll: scrollView,
progress,
controls,
location,
overview,
fragments,
backgrounds,
slideContent,
slideNumber,

585
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "reveal.js",
"version": "4.5.0",
"version": "4.6.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "reveal.js",
"version": "4.5.0",
"version": "4.6.1",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.14.3",
@@ -42,12 +42,16 @@
}
},
"node_modules/@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true,
"dependencies": {
"@babel/highlight": "^7.12.13"
"@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/compat-data": {
@@ -105,14 +109,18 @@
}
},
"node_modules/@babel/generator": {
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz",
"integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true,
"dependencies": {
"@babel/types": "^7.14.2",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
"@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-annotate-as-pure": {
@@ -198,6 +206,15 @@
"@babel/core": "^7.4.0-0"
}
},
"node_modules/@babel/helper-environment-visitor": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-explode-assignable-expression": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz",
@@ -208,33 +225,28 @@
}
},
"node_modules/@babel/helper-function-name": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz",
"integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true,
"dependencies": {
"@babel/helper-get-function-arity": "^7.12.13",
"@babel/template": "^7.12.13",
"@babel/types": "^7.14.2"
}
},
"node_modules/@babel/helper-get-function-arity": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
"integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
"dev": true,
"dependencies": {
"@babel/types": "^7.12.13"
"@babel/template": "^7.22.15",
"@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-hoist-variables": {
"version": "7.13.16",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz",
"integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true,
"dependencies": {
"@babel/traverse": "^7.13.15",
"@babel/types": "^7.13.16"
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
@@ -328,19 +340,34 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
"integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"dependencies": {
"@babel/types": "^7.12.13"
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"dev": true
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
"version": "7.12.17",
@@ -372,20 +399,23 @@
}
},
"node_modules/@babel/highlight": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.14.0",
"chalk": "^2.0.0",
"@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz",
"integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -1300,40 +1330,52 @@
}
},
"node_modules/@babel/template": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
"integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
"@babel/parser": "^7.12.13",
"@babel/types": "^7.12.13"
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz",
"integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==",
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.2",
"@babel/helper-function-name": "^7.14.2",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.14.2",
"@babel/types": "^7.14.2",
"@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0",
"@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz",
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.14.0",
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@eslint/eslintrc": {
@@ -2197,26 +2239,35 @@
}
},
"node_modules/browserslist": {
"version": "4.19.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz",
"integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==",
"version": "4.21.10",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
"integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"caniuse-lite": "^1.0.30001312",
"electron-to-chromium": "^1.4.71",
"escalade": "^3.1.1",
"node-releases": "^2.0.2",
"picocolors": "^1.0.0"
"caniuse-lite": "^1.0.30001517",
"electron-to-chromium": "^1.4.477",
"node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.11"
},
"bin": {
"browserslist": "cli.js"
},
"engines": {
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
}
},
"node_modules/buffer": {
@@ -2337,9 +2388,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001374",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
"version": "1.0.30001538",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
"integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
"dev": true,
"funding": [
{
@@ -2349,6 +2400,10 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
},
@@ -2854,28 +2909,18 @@
}
},
"node_modules/core-js-compat": {
"version": "3.12.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz",
"integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==",
"version": "3.32.2",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
"integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
"dev": true,
"dependencies": {
"browserslist": "^4.16.6",
"semver": "7.0.0"
"browserslist": "^4.21.10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/core-js-compat/node_modules/semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -3155,9 +3200,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.4.73",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz",
"integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==",
"version": "1.4.526",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.526.tgz",
"integrity": "sha512-tjjTMjmZAx1g6COrintLTa2/jcafYKxKoiEkdQOrVdbLaHh2wCt2nsAF8ZHweezkrP+dl/VG9T5nabcYoo0U5Q==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -3476,9 +3521,9 @@
}
},
"node_modules/eslint/node_modules/semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"peer": true,
"dependencies": {
@@ -4754,9 +4799,9 @@
}
},
"node_modules/gulp-eslint/node_modules/cross-spawn/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -6451,10 +6496,16 @@
"dev": true
},
"node_modules/nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -6591,9 +6642,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
"integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true
},
"node_modules/node-watch": {
@@ -6618,9 +6669,9 @@
}
},
"node_modules/normalize-package-data/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -7251,21 +7302,31 @@
}
},
"node_modules/postcss": {
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz",
"integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==",
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.1",
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
}
},
"node_modules/postcss-value-parser": {
@@ -7966,9 +8027,9 @@
}
},
"node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@@ -9406,6 +9467,36 @@
"node": ">=0.10.0"
}
},
"node_modules/update-browserslist-db": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.12.tgz",
"integrity": "sha512-tE1smlR58jxbFMtrMpFNRmsrOXlpNXss965T1CrpwuZUzUAg/TBQc94SpyhDLSzrqrJS9xTRBthnZAGcE1oaxg==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
},
"bin": {
"update-browserslist-db": "cli.js"
},
"peerDependencies": {
"browserslist": ">= 4.21.0"
}
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -9629,9 +9720,9 @@
"dev": true
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -9802,12 +9893,13 @@
},
"dependencies": {
"@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true,
"requires": {
"@babel/highlight": "^7.12.13"
"@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
}
},
"@babel/compat-data": {
@@ -9851,14 +9943,15 @@
}
},
"@babel/generator": {
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz",
"integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true,
"requires": {
"@babel/types": "^7.14.2",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
"@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
}
},
"@babel/helper-annotate-as-pure": {
@@ -9932,6 +10025,12 @@
"semver": "^6.1.2"
}
},
"@babel/helper-environment-visitor": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true
},
"@babel/helper-explode-assignable-expression": {
"version": "7.13.0",
"resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz",
@@ -9942,33 +10041,22 @@
}
},
"@babel/helper-function-name": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz",
"integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true,
"requires": {
"@babel/helper-get-function-arity": "^7.12.13",
"@babel/template": "^7.12.13",
"@babel/types": "^7.14.2"
}
},
"@babel/helper-get-function-arity": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
"integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
"dev": true,
"requires": {
"@babel/types": "^7.12.13"
"@babel/template": "^7.22.15",
"@babel/types": "^7.23.0"
}
},
"@babel/helper-hoist-variables": {
"version": "7.13.16",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz",
"integrity": "sha512-1eMtTrXtrwscjcAeO4BVK+vvkxaLJSPFz1w1KLawz6HLNi9bPFGBNwwDyVfiu1Tv/vRRFYfoGaKhmAQPGPn5Wg==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true,
"requires": {
"@babel/traverse": "^7.13.15",
"@babel/types": "^7.13.16"
"@babel/types": "^7.22.5"
}
},
"@babel/helper-member-expression-to-functions": {
@@ -10062,18 +10150,24 @@
}
},
"@babel/helper-split-export-declaration": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
"integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"requires": {
"@babel/types": "^7.12.13"
"@babel/types": "^7.22.5"
}
},
"@babel/helper-string-parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true
},
"@babel/helper-validator-identifier": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz",
"integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true
},
"@babel/helper-validator-option": {
@@ -10106,20 +10200,20 @@
}
},
"@babel/highlight": {
"version": "7.14.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz",
"integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"chalk": "^2.0.0",
"@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
"version": "7.14.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.3.tgz",
"integrity": "sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true
},
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
@@ -10833,39 +10927,42 @@
}
},
"@babel/template": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
"integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/parser": "^7.12.13",
"@babel/types": "^7.12.13"
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
}
},
"@babel/traverse": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz",
"integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==",
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.14.2",
"@babel/helper-function-name": "^7.14.2",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.14.2",
"@babel/types": "^7.14.2",
"@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.23.0",
"@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.14.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.2.tgz",
"integrity": "sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.14.0",
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
}
},
@@ -11529,16 +11626,15 @@
}
},
"browserslist": {
"version": "4.19.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz",
"integrity": "sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg==",
"version": "4.21.10",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
"integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001312",
"electron-to-chromium": "^1.4.71",
"escalade": "^3.1.1",
"node-releases": "^2.0.2",
"picocolors": "^1.0.0"
"caniuse-lite": "^1.0.30001517",
"electron-to-chromium": "^1.4.477",
"node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.11"
}
},
"buffer": {
@@ -11621,9 +11717,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001374",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001374.tgz",
"integrity": "sha512-mWvzatRx3w+j5wx/mpFN5v5twlPrabG8NqX2c6e45LCpymdoGqNvRkRutFUqpRTXKFQFNQJasvK0YT7suW6/Hw==",
"version": "1.0.30001538",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz",
"integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==",
"dev": true
},
"chalk": {
@@ -12036,21 +12132,12 @@
"dev": true
},
"core-js-compat": {
"version": "3.12.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.12.1.tgz",
"integrity": "sha512-i6h5qODpw6EsHAoIdQhKoZdWn+dGBF3dSS8m5tif36RlWvW3A6+yu2S16QHUo3CrkzrnEskMAt9f8FxmY9fhWQ==",
"version": "3.32.2",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
"integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
"dev": true,
"requires": {
"browserslist": "^4.16.6",
"semver": "7.0.0"
},
"dependencies": {
"semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true
}
"browserslist": "^4.21.10"
}
},
"core-util-is": {
@@ -12277,9 +12364,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.4.73",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.73.tgz",
"integrity": "sha512-RlCffXkE/LliqfA5m29+dVDPB2r72y2D2egMMfIy3Le8ODrxjuZNVo4NIC2yPL01N4xb4nZQLwzi6Z5tGIGLnA==",
"version": "1.4.526",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.526.tgz",
"integrity": "sha512-tjjTMjmZAx1g6COrintLTa2/jcafYKxKoiEkdQOrVdbLaHh2wCt2nsAF8ZHweezkrP+dl/VG9T5nabcYoo0U5Q==",
"dev": true
},
"emoji-regex": {
@@ -12505,9 +12592,9 @@
"peer": true
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"peer": true,
"requires": {
@@ -13577,9 +13664,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -14919,9 +15006,9 @@
"dev": true
},
"nanoid": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true
},
"nanomatch": {
@@ -15023,9 +15110,9 @@
}
},
"node-releases": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz",
"integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==",
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true
},
"node-watch": {
@@ -15047,9 +15134,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -15520,12 +15607,12 @@
"dev": true
},
"postcss": {
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.7.tgz",
"integrity": "sha512-L9Ye3r6hkkCeOETQX6iOaWZgjp3LL6Lpqm6EtgbKrgqGGteRMNb9vzBfRL96YOSu8o7x3MfIH9Mo5cPJFGrW6A==",
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"requires": {
"nanoid": "^3.3.1",
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
@@ -16081,9 +16168,9 @@
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
},
"semver-greatest-satisfied-range": {
@@ -17299,6 +17386,16 @@
}
}
},
"update-browserslist-db": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.12.tgz",
"integrity": "sha512-tE1smlR58jxbFMtrMpFNRmsrOXlpNXss965T1CrpwuZUzUAg/TBQc94SpyhDLSzrqrJS9xTRBthnZAGcE1oaxg==",
"dev": true,
"requires": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
}
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -17487,9 +17584,9 @@
"dev": true
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true
},
"wrap-ansi": {

View File

@@ -1,6 +1,6 @@
{
"name": "reveal.js",
"version": "4.5.0",
"version": "5.0.0",
"description": "The HTML Presentation Framework",
"homepage": "https://revealjs.com",
"subdomain": "revealjs",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -7,13 +7,16 @@
import { marked } from 'marked';
const DEFAULT_SLIDE_SEPARATOR = '\r?\n---\r?\n',
DEFAULT_NOTES_SEPARATOR = 'notes?:',
DEFAULT_VERTICAL_SEPARATOR = null,
DEFAULT_NOTES_SEPARATOR = '^\s*notes?:',
DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';
const SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__';
const CODE_LINE_NUMBER_REGEX = /\[([\s\d,|-]*)\]/;
// match an optional line number offset and highlight line numbers
// [<line numbers>] or [<offset>: <line numbers>]
const CODE_LINE_NUMBER_REGEX = /\[\s*((\d*):)?\s*([\s\d,|-]*)\]/;
const HTML_ESCAPE_MAP = {
'&': '&amp;',
@@ -35,15 +38,15 @@ const Plugin = () => {
function getMarkdownFromSlide( section ) {
// look for a <script> or <textarea data-template> wrapper
var template = section.querySelector( '[data-template]' ) || section.querySelector( 'script' );
const template = section.querySelector( '[data-template]' ) || section.querySelector( 'script' );
// strip leading whitespace so it isn't evaluated as code
var text = ( template || section ).textContent;
let text = ( template || section ).textContent;
// restore script end tags
text = text.replace( new RegExp( SCRIPT_END_PLACEHOLDER, 'g' ), '</script>' );
var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
const leadingWs = text.match( /^\n?(\s*)/ )[1].length,
leadingTabs = text.match( /^\n?(\t*)/ )[1].length;
if( leadingTabs > 0 ) {
@@ -65,11 +68,11 @@ const Plugin = () => {
*/
function getForwardedAttributes( section ) {
var attributes = section.attributes;
var result = [];
const attributes = section.attributes;
const result = [];
for( var i = 0, len = attributes.length; i < len; i++ ) {
var name = attributes[i].name,
for( let i = 0, len = attributes.length; i < len; i++ ) {
const name = attributes[i].name,
value = attributes[i].value;
// disregard attributes that are used for markdown loading/parsing
@@ -92,10 +95,12 @@ const Plugin = () => {
* values for what's not defined.
*/
function getSlidifyOptions( options ) {
const markdownConfig = deck.getConfig().markdown;
options = options || {};
options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
options.separator = options.separator || markdownConfig?.separator || DEFAULT_SLIDE_SEPARATOR;
options.verticalSeparator = options.verticalSeparator || markdownConfig?.verticalSeparator || DEFAULT_VERTICAL_SEPARATOR;
options.notesSeparator = options.notesSeparator || markdownConfig?.notesSeparator || DEFAULT_NOTES_SEPARATOR;
options.attributes = options.attributes || '';
return options;
@@ -109,7 +114,7 @@ const Plugin = () => {
options = getSlidifyOptions( options );
var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
const notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
if( notesMatch.length === 2 ) {
content = notesMatch[0] + '<aside class="notes">' + marked(notesMatch[1].trim()) + '</aside>';
@@ -131,10 +136,10 @@ const Plugin = () => {
options = getSlidifyOptions( options );
var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
const separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
horizontalSeparatorRegex = new RegExp( options.separator );
var matches,
let matches,
lastIndex = 0,
isHorizontal,
wasHorizontal = true,
@@ -143,7 +148,7 @@ const Plugin = () => {
// iterate until all blocks between separators are stacked up
while( matches = separatorRegex.exec( markdown ) ) {
var notes = null;
const notes = null;
// determine direction (horizontal by default)
isHorizontal = horizontalSeparatorRegex.test( matches[0] );
@@ -172,10 +177,10 @@ const Plugin = () => {
// add the remaining slide
( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
var markdownSections = '';
let markdownSections = '';
// flatten the hierarchical stack, and insert <section data-markdown> tags
for( var i = 0, len = sectionStack.length; i < len; i++ ) {
for( let i = 0, len = sectionStack.length; i < len; i++ ) {
// vertical
if( sectionStack[i] instanceof Array ) {
markdownSections += '<section '+ options.attributes +'>';
@@ -204,7 +209,7 @@ const Plugin = () => {
return new Promise( function( resolve ) {
var externalPromises = [];
const externalPromises = [];
[].slice.call( scope.querySelectorAll( 'section[data-markdown]:not([data-markdown-parsed])') ).forEach( function( section, i ) {
@@ -257,13 +262,13 @@ const Plugin = () => {
return new Promise( function( resolve, reject ) {
var xhr = new XMLHttpRequest(),
const xhr = new XMLHttpRequest(),
url = section.getAttribute( 'data-markdown' );
var datacharset = section.getAttribute( 'data-charset' );
const datacharset = section.getAttribute( 'data-charset' );
// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
if( datacharset != null && datacharset != '' ) {
if( datacharset !== null && datacharset !== '' ) {
xhr.overrideMimeType( 'text/html; charset=' + datacharset );
}
@@ -308,17 +313,17 @@ const Plugin = () => {
*/
function addAttributeInElement( node, elementTarget, separator ) {
var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"]+?)\"|(data-[^\"= ]+?)(?=[\" ])", 'mg' );
var nodeValue = node.nodeValue;
var matches,
const markdownClassesInElementsRegex = new RegExp( separator, 'mg' );
const markdownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"]+?)\"|(data-[^\"= ]+?)(?=[\" ])", 'mg' );
let nodeValue = node.nodeValue;
let matches,
matchesClass;
if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
if( matches = markdownClassesInElementsRegex.exec( nodeValue ) ) {
var classes = matches[1];
nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
const classes = matches[1];
nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( markdownClassesInElementsRegex.lastIndex );
node.nodeValue = nodeValue;
while( matchesClass = mardownClassRegex.exec( classes ) ) {
while( matchesClass = markdownClassRegex.exec( classes ) ) {
if( matchesClass[2] ) {
elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
} else {
@@ -336,34 +341,34 @@ const Plugin = () => {
*/
function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {
if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
var previousParentElement = element;
for( var i = 0; i < element.childNodes.length; i++ ) {
var childElement = element.childNodes[i];
if ( element !== null && element.childNodes !== undefined && element.childNodes.length > 0 ) {
let previousParentElement = element;
for( let i = 0; i < element.childNodes.length; i++ ) {
const childElement = element.childNodes[i];
if ( i > 0 ) {
var j = i - 1;
let j = i - 1;
while ( j >= 0 ) {
var aPreviousChildElement = element.childNodes[j];
if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
const aPreviousChildElement = element.childNodes[j];
if ( typeof aPreviousChildElement.setAttribute === 'function' && aPreviousChildElement.tagName !== "BR" ) {
previousParentElement = aPreviousChildElement;
break;
}
j = j - 1;
}
}
var parentSection = section;
if( childElement.nodeName == "section" ) {
let parentSection = section;
if( childElement.nodeName === "section" ) {
parentSection = childElement ;
previousParentElement = childElement ;
}
if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
if ( typeof childElement.setAttribute === 'function' || childElement.nodeType === Node.COMMENT_NODE ) {
addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
}
}
}
if ( element.nodeType == Node.COMMENT_NODE ) {
if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
if ( element.nodeType === Node.COMMENT_NODE ) {
if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) === false ) {
addAttributeInElement( element, section, separatorSectionAttributes );
}
}
@@ -375,14 +380,14 @@ const Plugin = () => {
*/
function convertSlides() {
var sections = deck.getRevealElement().querySelectorAll( '[data-markdown]:not([data-markdown-parsed])');
const sections = deck.getRevealElement().querySelectorAll( '[data-markdown]:not([data-markdown-parsed])');
[].slice.call( sections ).forEach( function( section ) {
section.setAttribute( 'data-markdown-parsed', true )
var notes = section.querySelector( 'aside.notes' );
var markdown = getMarkdownFromSlide( section );
const notes = section.querySelector( 'aside.notes' );
const markdown = getMarkdownFromSlide( section );
section.innerHTML = marked( markdown );
addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
@@ -429,14 +434,23 @@ const Plugin = () => {
renderer.code = ( code, language ) => {
// Off by default
let lineNumberOffset = '';
let lineNumbers = '';
// Users can opt in to show line numbers and highlight
// specific lines.
// ```javascript [] show line numbers
// ```javascript [1,4-8] highlights lines 1 and 4-8
// optional line number offset:
// ```javascript [25: 1,4-8] start line numbering at 25,
// highlights lines 1 (numbered as 25) and 4-8 (numbered as 28-32)
if( CODE_LINE_NUMBER_REGEX.test( language ) ) {
lineNumbers = language.match( CODE_LINE_NUMBER_REGEX )[1].trim();
let lineNumberOffsetMatch = language.match( CODE_LINE_NUMBER_REGEX )[2];
if (lineNumberOffsetMatch){
lineNumberOffset = `data-ln-start-from="${lineNumberOffsetMatch.trim()}"`;
}
lineNumbers = language.match( CODE_LINE_NUMBER_REGEX )[3].trim();
lineNumbers = `data-line-numbers="${lineNumbers}"`;
language = language.replace( CODE_LINE_NUMBER_REGEX, '' ).trim();
}
@@ -446,7 +460,9 @@ const Plugin = () => {
// highlight.js is able to read it
code = escapeForHTML( code );
return `<pre><code ${lineNumbers} class="${language}">${code}</code></pre>`;
// return `<pre><code ${lineNumbers} class="${language}">${code}</code></pre>`;
return `<pre><code ${lineNumbers} ${lineNumberOffset} class="${language}">${code}</code></pre>`;
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -146,8 +146,12 @@ const Plugin = () => {
}
// Look for notes defined in an aside element
if( notesElements ) {
messageData.notes = Array.from(notesElements).map( notesElement => notesElement.innerHTML ).join( '\n' );
if( notesElements && notesElements.length ) {
// Ignore notes inside of fragments since those are shown
// individually when stepping through fragments
notesElements = Array.from( notesElements ).filter( notesElement => notesElement.closest( '.fragment' ) === null );
messageData.notes = notesElements.map( notesElement => notesElement.innerHTML ).join( '\n' );
messageData.markdown = notesElements[0] && typeof notesElements[0].getAttribute( 'data-markdown' ) === 'string';
}

View File

@@ -274,6 +274,13 @@
```
</script>
</section>
<section data-markdown class="with-offset">
<script type="text/template">
```[123:]
code
```
</script>
</section>
<section data-markdown class="with-line-highlights-and-lanugage">
<script type="text/template">
```javascript [1,2,3]
@@ -281,6 +288,20 @@
```
</script>
</section>
<section data-markdown class="with-line-highlights-offset-and-lanugage">
<script type="text/template">
```javascript [456: 3,4,5]
code
```
</script>
</section>
<section data-markdown class="with-line-offset-and-lanugage">
<script type="text/template">
```javascript [756:]
code
```
</script>
</section>
<section data-markdown class="with-code-in-fragment">
<script type="text/template">
```js
@@ -460,9 +481,22 @@
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-line-highlights .hljs[data-line-numbers="1,2,3"]' ).length, 1 );
});
QUnit.test( '```[234: ] line offset only', function( assert ) {
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-offset .hljs[data-ln-start-from="123"]' ).length, 1 );
});
QUnit.test( '```javascript [1,2,3] enables line highlights and sets language', function( assert ) {
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-line-highlights-and-lanugage .hljs.javascript[data-line-numbers="1,2,3"]' ).length, 1 );
});
QUnit.test( '```javascript [123: 3,4,5] add line offset and enables line highlights and sets language', function( assert ) {
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-line-highlights-offset-and-lanugage .hljs.javascript[data-line-numbers="3,4,5"]' ).length, 1 );
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-line-highlights-offset-and-lanugage .hljs.javascript[data-ln-start-from="456"]' ).length, 1 );
});
QUnit.test( '```javascript [756:] add line offset and sets no line highlights and sets language', function( assert ) {
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-line-offset-and-lanugage .hljs.javascript[data-ln-start-from="756"]' ).length, 1 );
});
QUnit.test( '```block should allow custom fragment', function( assert ) {
assert.strictEqual( deck6.getRevealElement().querySelectorAll( '.with-code-in-fragment pre.fragment' ).length, 1 );

115
test/test-scroll.html Normal file
View File

@@ -0,0 +1,115 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Test Scroll View</title>
<link rel="stylesheet" href="../dist/reveal.css">
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css">
<script src="../node_modules/qunit/qunit/qunit.js"></script>
</head>
<body style="overflow: auto;">
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<div class="reveal" style="opacity: 0; pointer-events: none;">
<div class="slides">
<section>
<h1>slide 1</h1>
</section>
<section>
<h1>slide 2</h1>
</section>
<section>
<h1>slide 3</h1>
<p class="fragment">fragment 1</p>
<p class="fragment">fragment 2</p>
<p class="fragment">fragment 3</p>
</section>
<section>
<h1>slide 4</h1>
</section>
</div>
</div>
<script src="../dist/reveal.js"></script>
<script>
QUnit.config.testTimeout = 30000;
QUnit.config.reorder = false;
function getScrollHeight() {
return Reveal.getViewportElement().scrollHeight;
}
function getViewportHeight() {
return Reveal.getViewportElement().offsetHeight;
}
Reveal.initialize({ view: 'scroll' }).then( async () => {
QUnit.module( 'Scroll View' );
QUnit.test( 'Activates', assert => {
assert.ok( getScrollHeight() > getViewportHeight(), 'Is overflowing' );
});
QUnit.test( 'Can be toggled via API', assert => {
Reveal.toggleScrollView( false );
assert.ok( getScrollHeight() <= getViewportHeight(), 'Is not overflowing' );
Reveal.toggleScrollView( true );
assert.ok( getScrollHeight() > getViewportHeight(), 'Is overflowing' );
});
QUnit.test( 'Changes present slide when scrolling', assert => {
assert.timeout( 200 );
assert.expect( 2 );
const slides = document.querySelectorAll( '.reveal .slides section' );
assert.ok( slides[0].classList.contains( 'present' ), 'First slide is present' );
Reveal.getViewportElement().scrollTop = getViewportHeight() * 1;
return new Promise( resolve => {
setTimeout(() => {
assert.ok( slides[1].classList.contains( 'present' ), 'Second slide is present' );
resolve();
}, 100);
} );
});
QUnit.test( 'Fires slideschanged event when scrolling', assert => {
assert.timeout( 200 );
assert.expect( 2 );
const slides = document.querySelectorAll( '.reveal .slides section' );
return new Promise( resolve => {
let callback = ( event ) => {
Reveal.off( 'slidechanged', callback );
assert.ok( true, 'slidechanged event fired' );
assert.ok( event.currentSlide.classList.contains( 'present' ), 'slidechanged provides reference to currentSlide' );
resolve();
}
Reveal.on( 'slidechanged', callback );
Reveal.getViewportElement().scrollTop = getViewportHeight() * 2;
});
});
} );
</script>
</body>
</html>