Merge pull request #20 from msoedov/updatae_deps

Update deps
This commit is contained in:
Alex Miasoiedov 2017-11-20 18:09:52 -05:00 committed by GitHub
commit ce0bc9118b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 645 additions and 204 deletions

1
.gitignore vendored
View file

@ -24,3 +24,4 @@ bin/
src/ src/
slides/ slides/
main main
node_modules

View file

@ -1,13 +1,14 @@
GIT_SUMMARY := $(shell git describe --tags --dirty --always)
REPO=msoedov/hacker-slides REPO=msoedov/hacker-slides
default: repo default: repo
repo: repo:
@echo $(REPO) @echo $(REPO):$(GIT_SUMMARY)
build: build:
@GOOS=linux CGO_ENABLE=0 go build main.go @GOOS=linux CGO_ENABLE=0 go build main.go
@docker build -t $(REPO) . @docker build -t $(REPO):$(GIT_SUMMARY) .
push: push:
@docker push $(REPO) @docker push $(REPO):$(GIT_SUMMARY)

View file

@ -1,5 +1,5 @@
{ {
"dependencies": { "dependencies": {
"reveal.js": "^3.4.1" "reveal.js": "^3.5.0"
} }
} }

View file

@ -15,7 +15,7 @@ module.exports = function(grunt) {
' * http://lab.hakim.se/reveal-js\n' + ' * http://lab.hakim.se/reveal-js\n' +
' * MIT licensed\n' + ' * MIT licensed\n' +
' *\n' + ' *\n' +
' * Copyright (C) 2016 Hakim El Hattab, http://hakim.se\n' + ' * Copyright (C) 2017 Hakim El Hattab, http://hakim.se\n' +
' */' ' */'
}, },
@ -44,7 +44,7 @@ module.exports = function(grunt) {
{ {
expand: true, expand: true,
cwd: 'css/theme/source', cwd: 'css/theme/source',
src: ['*.scss'], src: ['*.sass', '*.scss'],
dest: 'css/theme', dest: 'css/theme',
ext: '.css' ext: '.css'
} }
@ -122,7 +122,12 @@ module.exports = function(grunt) {
tasks: 'js' tasks: 'js'
}, },
theme: { theme: {
files: [ 'css/theme/source/*.scss', 'css/theme/template/*.scss' ], files: [
'css/theme/source/*.sass',
'css/theme/source/*.scss',
'css/theme/template/*.sass',
'css/theme/template/*.scss'
],
tasks: 'css-themes' tasks: 'css-themes'
}, },
css: { css: {

View file

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

View file

@ -105,17 +105,17 @@ The presentation markup hierarchy needs to be `.reveal > .slides > section` wher
### Markdown ### Markdown
It's possible to write your slides using Markdown. To enable Markdown, add the `data-markdown` attribute to your `<section>` elements and wrap the contents in a `<script type="text/template">` like the example below. It's possible to write your slides using Markdown. To enable Markdown, add the `data-markdown` attribute to your `<section>` elements and wrap the contents in a `<textarea data-template>` like the example below.
This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) modified to use [marked](https://github.com/chjj/marked) to support [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown). Sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks). This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) modified to use [marked](https://github.com/chjj/marked) to support [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown). Sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks).
```html ```html
<section data-markdown> <section data-markdown>
<script type="text/template"> <textarea data-template>
## Page title ## Page title
A paragraph with some text and a [link](http://hakim.se). A paragraph with some text and a [link](http://hakim.se).
</script> </textarea>
</section> </section>
``` ```
@ -187,6 +187,9 @@ Reveal.initialize({
// Display a presentation progress bar // Display a presentation progress bar
progress: true, progress: true,
// Set default timing of 2 minutes per slide
defaultTiming: 120,
// Display the page number of the current slide // Display the page number of the current slide
slideNumber: false, slideNumber: false,
@ -228,6 +231,12 @@ Reveal.initialize({
// Flags if speaker notes should be visible to all viewers // Flags if speaker notes should be visible to all viewers
showNotes: false, showNotes: false,
// Global override for autolaying embedded media (video/audio/iframe)
// - null: Media will only autoplay if data-autoplay is present
// - true: All media will autoplay, regardless of individual setting
// - false: No media will autoplay, regardless of individual setting
autoPlayMedia: null,
// Number of milliseconds between automatically proceeding to the // Number of milliseconds between automatically proceeding to the
// next slide, disabled when set to 0, this value can be overwritten // next slide, disabled when set to 0, this value can be overwritten
// by using a data-autoslide attribute on your slides // by using a data-autoslide attribute on your slides
@ -270,7 +279,10 @@ Reveal.initialize({
// - Calculated automatically unless specified // - Calculated automatically unless specified
// - Set to 0 to disable movement along an axis // - Set to 0 to disable movement along an axis
parallaxBackgroundHorizontal: null, parallaxBackgroundHorizontal: null,
parallaxBackgroundVertical: null parallaxBackgroundVertical: null,
// The display mode that will be used to show slides
display: 'block'
}); });
``` ```
@ -463,14 +475,15 @@ Reveal.nextFragment();
// Randomize the order of slides // Randomize the order of slides
Reveal.shuffle(); Reveal.shuffle();
// Shows a help overlay with keyboard shortcuts
Reveal.showHelp();
// Toggle presentation states, optionally pass true/false to force on/off // Toggle presentation states, optionally pass true/false to force on/off
Reveal.toggleOverview(); Reveal.toggleOverview();
Reveal.togglePause(); Reveal.togglePause();
Reveal.toggleAutoSlide(); Reveal.toggleAutoSlide();
// Shows a help overlay with keyboard shortcuts, optionally pass true/false
// to force on/off
Reveal.toggleHelp();
// Change a config value at runtime // Change a config value at runtime
Reveal.configure({ controls: true }); Reveal.configure({ controls: true });
@ -484,9 +497,11 @@ Reveal.getScale();
Reveal.getPreviousSlide(); Reveal.getPreviousSlide();
Reveal.getCurrentSlide(); Reveal.getCurrentSlide();
Reveal.getIndices(); // { h: 0, v: 0 } } Reveal.getIndices(); // { h: 0, v: 0 } }
Reveal.getProgress(); // 0-1 Reveal.getPastSlideCount();
Reveal.getTotalSlides(); Reveal.getProgress(); // (0 == first slide, 1 == last slide)
Reveal.getSlides(); // Array of all slides
Reveal.getTotalSlides(); // total number of slides
// Returns the speaker notes for the current slide // Returns the speaker notes for the current slide
Reveal.getSlideNotes(); Reveal.getSlideNotes();
@ -544,7 +559,7 @@ Reveal.addEventListener( 'somestate', function() {
Slides are contained within a limited portion of the screen by default to allow them to fit any display and scale uniformly. You can apply full page backgrounds outside of the slide area by adding a ```data-background``` attribute to your ```<section>``` elements. Four different types of backgrounds are supported: color, image, video and iframe. Slides are contained within a limited portion of the screen by default to allow them to fit any display and scale uniformly. You can apply full page backgrounds outside of the slide area by adding a ```data-background``` attribute to your ```<section>``` elements. Four different types of backgrounds are supported: color, image, video and iframe.
##### Color Backgrounds #### Color Backgrounds
All CSS color formats are supported, like rgba() or hsl(). All CSS color formats are supported, like rgba() or hsl().
```html ```html
<section data-background-color="#ff0000"> <section data-background-color="#ff0000">
@ -552,7 +567,7 @@ All CSS color formats are supported, like rgba() or hsl().
</section> </section>
``` ```
##### Image Backgrounds #### Image Backgrounds
By default, background images are resized to cover the full page. Available options: By default, background images are resized to cover the full page. Available options:
| Attribute | Default | Description | | Attribute | Default | Description |
@ -570,7 +585,7 @@ By default, background images are resized to cover the full page. Available opti
</section> </section>
``` ```
##### Video Backgrounds #### Video Backgrounds
Automatically plays a full size video behind the slide. Automatically plays a full size video behind the slide.
| Attribute | Default | Description | | Attribute | Default | Description |
@ -578,6 +593,7 @@ Automatically plays a full size video behind the slide.
| data-background-video | | A single video source, or a comma separated list of video sources. | | data-background-video | | A single video source, or a comma separated list of video sources. |
| data-background-video-loop | false | Flags if the video should play repeatedly. | | data-background-video-loop | false | Flags if the video should play repeatedly. |
| data-background-video-muted | false | Flags if the audio should be muted. | | data-background-video-muted | false | Flags if the audio should be muted. |
| data-background-size | cover | Use `cover` for full screen and some cropping or `contain` for letterboxing. |
```html ```html
<section 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" data-background-video-loop data-background-video-muted> <section 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" data-background-video-loop data-background-video-muted>
@ -585,15 +601,15 @@ Automatically plays a full size video behind the slide.
</section> </section>
``` ```
##### Iframe Backgrounds #### Iframe Backgrounds
Embeds a web page as a background. Note that since the iframe is in the background layer, behind your slides, it is not possible to interact with the embedded page. Embeds a web page as a slide background that covers 100% of the reveal.js width and height. The iframe is in the background layer, behind your slides, and as such it's not possible to interact with it by default. To make your background interactive, you can add the `data-background-interactive` attribute.
```html ```html
<section data-background-iframe="https://slides.com"> <section data-background-iframe="https://slides.com" data-background-interactive>
<h2>Iframe</h2> <h2>Iframe</h2>
</section> </section>
``` ```
##### Background Transitions #### Background Transitions
Backgrounds transition using a fade animation by default. This can be changed to a linear sliding transition by passing ```backgroundTransition: 'slide'``` to the ```Reveal.initialize()``` call. Alternatively you can set ```data-background-transition``` on any section with a background to override that specific transition. Backgrounds transition using a fade animation by default. This can be changed to a linear sliding transition by passing ```backgroundTransition: 'slide'``` to the ```Reveal.initialize()``` call. Alternatively you can set ```data-background-transition``` on any section with a background to override that specific transition.
@ -749,7 +765,7 @@ By default, Reveal is configured with [highlight.js](https://highlightjs.org/) f
``` ```
### Slide number ### Slide number
If you would like to display the page number of the current slide you can do so using the ```slideNumber``` configuration value. If you would like to display the page number of the current slide you can do so using the ```slideNumber``` and ```showSlideNumber``` configuration values.
```javascript ```javascript
// Shows the slide number using default formatting // Shows the slide number using default formatting
@ -762,6 +778,12 @@ Reveal.configure({ slideNumber: true });
// "c/t": flattened slide number / total slides // "c/t": flattened slide number / total slides
Reveal.configure({ slideNumber: 'c/t' }); Reveal.configure({ slideNumber: 'c/t' });
// Control which views the slide number displays on using the "showSlideNumber" value:
// "all": show on all views (default)
// "speaker": only show slide numbers on speaker notes view
// "print": only show slide numbers when printing to PDF
Reveal.configure({ showSlideNumber: 'speaker' });
``` ```
@ -778,20 +800,26 @@ Reveal.addEventListener( 'overviewhidden', function( event ) { /* ... */ } );
Reveal.toggleOverview(); Reveal.toggleOverview();
``` ```
### Fullscreen mode ### Fullscreen mode
Just press »F« on your keyboard to show your presentation in fullscreen mode. Press the »ESC« key to exit fullscreen mode. Just press »F« on your keyboard to show your presentation in fullscreen mode. Press the »ESC« key to exit fullscreen mode.
### Embedded media ### Embedded media
Embedded HTML5 `<video>`/`<audio>` and YouTube iframes are automatically paused when you navigate away from a slide. This can be disabled by decorating your element with a `data-ignore` attribute.
Add `data-autoplay` to your media element if you want it to automatically start playing when the slide is shown: Add `data-autoplay` to your media element if you want it to automatically start playing when the slide is shown:
```html ```html
<video data-autoplay src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video> <video data-autoplay src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
``` ```
Additionally the framework automatically pushes two [post messages](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage) to all iframes, ```slide:start``` when the slide containing the iframe is made visible and ```slide:stop``` when it is hidden. If you want to enable or disable autoplay globally, for all embedded media, you can use the `autoPlayMedia` configuration option. If you set this to `true` ALL media will autoplay regardless of individual `data-autoplay` attributes. If you initialize with `autoPlayMedia: false` NO media will autoplay.
Note that embedded HTML5 `<video>`/`<audio>` and YouTube/Vimeo iframes are automatically paused when you navigate away from a slide. This can be disabled by decorating your element with a `data-ignore` attribute.
### Embedded iframes
reveal.js automatically pushes two [post messages](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage) to embedded iframes. ```slide:start``` when the slide containing the iframe is made visible and ```slide:stop``` when it is hidden.
### Stretching elements ### Stretching elements
@ -847,15 +875,31 @@ Reveal.initialize({
Presentations can be exported to PDF via a special print stylesheet. This feature requires that you use [Google Chrome](http://google.com/chrome) or [Chromium](https://www.chromium.org/Home) and to be serving the presention from a webserver. Presentations can be exported to PDF via a special print stylesheet. This feature requires that you use [Google Chrome](http://google.com/chrome) or [Chromium](https://www.chromium.org/Home) and to be serving the presention from a webserver.
Here's an example of an exported presentation that's been uploaded to SlideShare: http://www.slideshare.net/hakimel/revealjs-300. Here's an example of an exported presentation that's been uploaded to SlideShare: http://www.slideshare.net/hakimel/revealjs-300.
### Page size
Export dimensions are inferred from the configured [presentation size](#presentation-size). Slides that are too tall to fit within a single page will expand onto multiple pages. You can limit how many pages a slide may expand onto using the `pdfMaxPagesPerSlide` config option, for example `Reveal.configure({ pdfMaxPagesPerSlide: 1 })` ensures that no slide ever grows to more than one printed page. Export dimensions are inferred from the configured [presentation size](#presentation-size). Slides that are too tall to fit within a single page will expand onto multiple pages. You can limit how many pages a slide may expand onto using the `pdfMaxPagesPerSlide` config option, for example `Reveal.configure({ pdfMaxPagesPerSlide: 1 })` ensures that no slide ever grows to more than one printed page.
1. Open your presentation with `print-pdf` included in the query string i.e. http://localhost:8000/?print-pdf#/. This triggers the default index HTML to load the PDF print stylesheet ([css/print/pdf.css](https://github.com/hakimel/reveal.js/blob/master/css/print/pdf.css)). You can test this with [lab.hakim.se/reveal-js?print-pdf](http://lab.hakim.se/reveal-js?print-pdf). ### Print stylesheet
2. Open the in-browser print dialog (CTRL/CMD+P). To enable the PDF print capability in your presentation, the special print stylesheet at [/css/print/pdf.css](https://github.com/hakimel/reveal.js/blob/master/css/print/pdf.css) must be loaded. The default index.html file handles this for you when `print-pdf` is included in the query string. If you're using a different HTML template, you can add this to your HEAD:
3. Change the **Destination** setting to **Save as PDF**.
4. Change the **Layout** to **Landscape**. ```html
5. Change the **Margins** to **None**. <script>
6. Enable the **Background graphics** option. var link = document.createElement( 'link' );
7. Click **Save**. link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
```
### Instructions
1. Open your presentation with `print-pdf` included in the query string i.e. http://localhost:8000/?print-pdf. You can test this with [lab.hakim.se/reveal-js?print-pdf](http://lab.hakim.se/reveal-js?print-pdf).
* If you want to include [speaker notes](#speaker-notes) in your export, you can append `showNotes=true` to the query string: http://localhost:8000/?print-pdf&showNotes=true
1. Open the in-browser print dialog (CTRL/CMD+P).
1. Change the **Destination** setting to **Save as PDF**.
1. Change the **Layout** to **Landscape**.
1. Change the **Margins** to **None**.
1. Enable the **Background graphics** option.
1. Click **Save**.
![Chrome Print Settings](https://s3.amazonaws.com/hakim-static/reveal-js/pdf-print-settings-2.png) ![Chrome Print Settings](https://s3.amazonaws.com/hakim-static/reveal-js/pdf-print-settings-2.png)
@ -924,7 +968,18 @@ This will only display in the notes window.
Notes are only visible to the speaker inside of the speaker view. If you wish to share your notes with others you can initialize reveal.js with the `showNotes` config value set to `true`. Notes will appear along the bottom of the presentations. Notes are only visible to the speaker inside of the speaker view. If you wish to share your notes with others you can initialize reveal.js with the `showNotes` config value set to `true`. Notes will appear along the bottom of the presentations.
When `showNotes` is enabled notes are also included when you [export to PDF](https://github.com/hakimel/reveal.js#pdf-export). By default, notes are printed in a semi-transparent box on top of slide. If you'd rather print them on a separate page after the slide, set `showNotes: "separate-page"`. When `showNotes` is enabled notes are also included when you [export to PDF](https://github.com/hakimel/reveal.js#pdf-export). By default, notes are printed in a semi-transparent box on top of the slide. If you'd rather print them on a separate page after the slide, set `showNotes: "separate-page"`.
#### Speaker notes clock and timers
The speaker notes window will also show:
- Time elapsed since the beginning of the presentation. If you hover the mouse above this section, a timer reset button will appear.
- Current wall-clock time
- (Optionally) a pacing timer which indicates whether the current pace of the presentation is on track for the right timing (shown in green), and if not, whether the presenter should speed up (shown in red) or has the luxury of slowing down (blue).
The pacing timer can be enabled by configuring by the `defaultTiming` parameter in the `Reveal` configuration block, which specifies the number of seconds per slide. 120 can be a reasonable rule of thumb. Timings can also be given per slide `<section>` by setting the `data-timing` attribute. Both values are in numbers of seconds.
## Server Side Speaker Notes ## Server Side Speaker Notes
@ -1026,11 +1081,13 @@ Server that receives the slideChanged events from the master presentation and br
1. ```npm install``` 1. ```npm install```
2. ```node plugin/multiplex``` 2. ```node plugin/multiplex```
Or you use the socket.io server at [https://reveal-js-multiplex-ccjbegmaii.now.sh/](https://reveal-js-multiplex-ccjbegmaii.now.sh/). Or you can use the socket.io server at [https://reveal-js-multiplex-ccjbegmaii.now.sh/](https://reveal-js-multiplex-ccjbegmaii.now.sh/).
You'll need to generate a unique secret and token pair for your master and client presentations. To do so, visit ```http://example.com/token```, where ```http://example.com``` is the location of your socket.io server. Or if you're going to use the socket.io server at [https://reveal-js-multiplex-ccjbegmaii.now.sh/](https://reveal-js-multiplex-ccjbegmaii.now.sh/), visit [https://reveal-js-multiplex-ccjbegmaii.now.sh/token](https://reveal-js-multiplex-ccjbegmaii.now.sh/token). You'll need to generate a unique secret and token pair for your master and client presentations. To do so, visit ```http://example.com/token```, where ```http://example.com``` is the location of your socket.io server. Or if you're going to use the socket.io server at [https://reveal-js-multiplex-ccjbegmaii.now.sh/](https://reveal-js-multiplex-ccjbegmaii.now.sh/), visit [https://reveal-js-multiplex-ccjbegmaii.now.sh/token](https://reveal-js-multiplex-ccjbegmaii.now.sh/token).
You are very welcome to point your presentations at the Socket.io server running at [https://reveal-js-multiplex-ccjbegmaii.now.sh/](https://reveal-js-multiplex-ccjbegmaii.now.sh/), but availability and stability are not guaranteed. For anything mission critical I recommend you run your own server. It is simple to deploy to nodejitsu, heroku, your own environment, etc. You are very welcome to point your presentations at the Socket.io server running at [https://reveal-js-multiplex-ccjbegmaii.now.sh/](https://reveal-js-multiplex-ccjbegmaii.now.sh/), but availability and stability are not guaranteed.
For anything mission critical I recommend you run your own server. The easiest way to do this is by installing [now](https://zeit.co/now). With that installed, deploying your own Multiplex server is as easy running the following command from the reveal.js folder: `now plugin/multiplex`.
##### socket.io server as file static server ##### socket.io server as file static server
@ -1096,7 +1153,7 @@ Reveal.initialize({
// other options ... // other options ...
math: { math: {
mathjax: 'https://cdn.mathjax.org/mathjax/latest/MathJax.js', mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',
config: 'TeX-AMS_HTML-full' // See http://docs.mathjax.org/en/latest/config-files.html config: 'TeX-AMS_HTML-full' // See http://docs.mathjax.org/en/latest/config-files.html
}, },
@ -1153,7 +1210,7 @@ Some reveal.js features, like external Markdown and speaker notes, require that
1. Open <http://localhost:8000> to view your presentation 1. Open <http://localhost:8000> to view your presentation
You can change the port by using `npm start -- --port 8001`. You can change the port by using `npm start -- --port=8001`.
### Folder Structure ### Folder Structure
@ -1167,4 +1224,4 @@ Some reveal.js features, like external Markdown and speaker notes, require that
MIT licensed MIT licensed
Copyright (C) 2016 Hakim El Hattab, http://hakim.se Copyright (C) 2017 Hakim El Hattab, http://hakim.se

View file

@ -1,6 +1,6 @@
{ {
"name": "reveal.js", "name": "reveal.js",
"version": "3.4.1", "version": "3.5.0",
"main": [ "main": [
"js/reveal.js", "js/reveal.js",
"css/reveal.css" "css/reveal.css"

View file

@ -87,14 +87,14 @@ ul, ol, div, p {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
z-index: 1; z-index: 1;
page-break-after: always;
} }
.reveal .slides section { .reveal .slides section {
page-break-after: always !important;
visibility: visible !important; visibility: visible !important;
display: block !important; display: block !important;
position: relative !important; position: absolute !important;
margin: 0 !important; margin: 0 !important;
padding: 0 !important; padding: 0 !important;
@ -115,6 +115,7 @@ ul, ol, div, p {
} }
.reveal section.stack { .reveal section.stack {
position: relative !important;
margin: 0 !important; margin: 0 !important;
padding: 0 !important; padding: 0 !important;
page-break-after: avoid !important; page-break-after: avoid !important;

View file

@ -3,7 +3,7 @@
* http://lab.hakim.se/reveal-js * http://lab.hakim.se/reveal-js
* MIT licensed * MIT licensed
* *
* Copyright (C) 2016 Hakim El Hattab, http://hakim.se * Copyright (C) 2017 Hakim El Hattab, http://hakim.se
*/ */
/********************************************* /*********************************************
* RESET STYLES * RESET STYLES
@ -323,6 +323,7 @@ body {
bottom: 0; bottom: 0;
left: 0; left: 0;
margin: auto; margin: auto;
pointer-events: none;
overflow: visible; overflow: visible;
z-index: 1; z-index: 1;
text-align: center; text-align: center;
@ -340,6 +341,7 @@ body {
position: absolute; position: absolute;
width: 100%; width: 100%;
padding: 20px 0px; padding: 20px 0px;
pointer-events: auto;
z-index: 10; z-index: 10;
-webkit-transform-style: flat; -webkit-transform-style: flat;
transform-style: flat; transform-style: flat;
@ -374,6 +376,12 @@ body {
z-index: 11; z-index: 11;
opacity: 1; } opacity: 1; }
.reveal .slides > section:empty,
.reveal .slides > section > section:empty,
.reveal .slides > section[data-background-interactive],
.reveal .slides > section > section[data-background-interactive] {
pointer-events: none; }
.reveal.center, .reveal.center,
.reveal.center .slides, .reveal.center .slides,
.reveal.center .slides section { .reveal.center .slides section {
@ -589,6 +597,10 @@ body {
/********************************************* /*********************************************
* CUBE TRANSITION * CUBE TRANSITION
*
* WARNING:
* this is deprecated and will be removed in a
* future version.
*********************************************/ *********************************************/
.reveal.cube .slides { .reveal.cube .slides {
-webkit-perspective: 1300px; -webkit-perspective: 1300px;
@ -664,6 +676,10 @@ body {
/********************************************* /*********************************************
* PAGE TRANSITION * PAGE TRANSITION
*
* WARNING:
* this is deprecated and will be removed in a
* future version.
*********************************************/ *********************************************/
.reveal.page .slides { .reveal.page .slides {
-webkit-perspective-origin: 0% 50%; -webkit-perspective-origin: 0% 50%;
@ -839,6 +855,7 @@ body {
height: 100%; height: 100%;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
overflow: hidden;
background-color: transparent; background-color: transparent;
background-position: 50% 50%; background-position: 50% 50%;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -851,7 +868,8 @@ body {
.reveal .slide-background.present { .reveal .slide-background.present {
opacity: 1; opacity: 1;
visibility: visible; } visibility: visible;
z-index: 2; }
.print-pdf .reveal .slide-background { .print-pdf .reveal .slide-background {
opacity: 1 !important; opacity: 1 !important;
@ -865,7 +883,13 @@ body {
max-width: none; max-width: none;
max-height: none; max-height: none;
top: 0; top: 0;
left: 0; } left: 0;
-o-object-fit: cover;
object-fit: cover; }
.reveal .slide-background[data-background-size="contain"] video {
-o-object-fit: contain;
object-fit: contain; }
/* Immediate transition style */ /* Immediate transition style */
.reveal[data-background-transition=none] > .backgrounds .slide-background, .reveal[data-background-transition=none] > .backgrounds .slide-background,
@ -1037,6 +1061,8 @@ body {
visibility: visible; visibility: visible;
outline: 10px solid rgba(150, 150, 150, 0.1); outline: 10px solid rgba(150, 150, 150, 0.1);
outline-offset: 10px; } outline-offset: 10px; }
.reveal.overview .backgrounds .slide-background.stack {
overflow: visible; }
.reveal.overview .slides section, .reveal.overview .slides section,
.reveal.overview-deactivating .slides section { .reveal.overview-deactivating .slides section {
@ -1048,10 +1074,6 @@ body {
-webkit-transition: none; -webkit-transition: none;
transition: none; } transition: none; }
.reveal.overview-animated .slides {
-webkit-transition: -webkit-transform 0.4s ease;
transition: transform 0.4s ease; }
/********************************************* /*********************************************
* RTL SUPPORT * RTL SUPPORT
*********************************************/ *********************************************/

View file

@ -3,7 +3,7 @@
* http://lab.hakim.se/reveal-js * http://lab.hakim.se/reveal-js
* MIT licensed * MIT licensed
* *
* Copyright (C) 2016 Hakim El Hattab, http://hakim.se * Copyright (C) 2017 Hakim El Hattab, http://hakim.se
*/ */
@ -388,6 +388,7 @@ body {
bottom: 0; bottom: 0;
left: 0; left: 0;
margin: auto; margin: auto;
pointer-events: none;
overflow: visible; overflow: visible;
z-index: 1; z-index: 1;
@ -406,6 +407,7 @@ body {
position: absolute; position: absolute;
width: 100%; width: 100%;
padding: 20px 0px; padding: 20px 0px;
pointer-events: auto;
z-index: 10; z-index: 10;
transform-style: flat; transform-style: flat;
@ -443,6 +445,13 @@ body {
opacity: 1; opacity: 1;
} }
.reveal .slides>section:empty,
.reveal .slides>section>section:empty,
.reveal .slides>section[data-background-interactive],
.reveal .slides>section>section[data-background-interactive] {
pointer-events: none;
}
.reveal.center, .reveal.center,
.reveal.center .slides, .reveal.center .slides,
.reveal.center .slides section { .reveal.center .slides section {
@ -610,6 +619,10 @@ body {
/********************************************* /*********************************************
* CUBE TRANSITION * CUBE TRANSITION
*
* WARNING:
* this is deprecated and will be removed in a
* future version.
*********************************************/ *********************************************/
.reveal.cube .slides { .reveal.cube .slides {
@ -682,6 +695,10 @@ body {
/********************************************* /*********************************************
* PAGE TRANSITION * PAGE TRANSITION
*
* WARNING:
* this is deprecated and will be removed in a
* future version.
*********************************************/ *********************************************/
.reveal.page .slides { .reveal.page .slides {
@ -866,6 +883,7 @@ body {
height: 100%; height: 100%;
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
overflow: hidden;
background-color: rgba( 0, 0, 0, 0 ); background-color: rgba( 0, 0, 0, 0 );
background-position: 50% 50%; background-position: 50% 50%;
@ -882,6 +900,7 @@ body {
.reveal .slide-background.present { .reveal .slide-background.present {
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
z-index: 2;
} }
.print-pdf .reveal .slide-background { .print-pdf .reveal .slide-background {
@ -898,7 +917,11 @@ body {
max-height: none; max-height: none;
top: 0; top: 0;
left: 0; left: 0;
object-fit: cover;
} }
.reveal .slide-background[data-background-size="contain"] video {
object-fit: contain;
}
/* Immediate transition style */ /* Immediate transition style */
.reveal[data-background-transition=none]>.backgrounds .slide-background, .reveal[data-background-transition=none]>.backgrounds .slide-background,
@ -1080,6 +1103,10 @@ body {
outline: 10px solid rgba(150,150,150,0.1); outline: 10px solid rgba(150,150,150,0.1);
outline-offset: 10px; outline-offset: 10px;
} }
.backgrounds .slide-background.stack {
overflow: visible;
}
} }
// Disable transitions transitions while we're activating // Disable transitions transitions while we're activating
@ -1094,10 +1121,6 @@ body {
transition: none; transition: none;
} }
.reveal.overview-animated .slides {
transition: transform 0.4s ease;
}
/********************************************* /*********************************************
* RTL SUPPORT * RTL SUPPORT

View file

@ -33,11 +33,10 @@
<script src="js/reveal.js"></script> <script src="js/reveal.js"></script>
<script> <script>
// More info https://github.com/hakimel/reveal.js#configuration // More info about config & dependencies:
// - https://github.com/hakimel/reveal.js#configuration
// - https://github.com/hakimel/reveal.js#dependencies
Reveal.initialize({ Reveal.initialize({
history: true,
// More info https://github.com/hakimel/reveal.js#dependencies
dependencies: [ dependencies: [
{ src: 'plugin/markdown/marked.js' }, { src: 'plugin/markdown/marked.js' },
{ src: 'plugin/markdown/markdown.js' }, { src: 'plugin/markdown/markdown.js' },

View file

@ -3,7 +3,7 @@
* http://lab.hakim.se/reveal-js * http://lab.hakim.se/reveal-js
* MIT licensed * MIT licensed
* *
* Copyright (C) 2016 Hakim El Hattab, http://hakim.se * Copyright (C) 2017 Hakim El Hattab, http://hakim.se
*/ */
(function( root, factory ) { (function( root, factory ) {
if( typeof define === 'function' && define.amd ) { if( typeof define === 'function' && define.amd ) {
@ -26,7 +26,7 @@
var Reveal; var Reveal;
// The reveal.js version // The reveal.js version
var VERSION = '3.4.1'; var VERSION = '3.5.0';
var SLIDES_SELECTOR = '.slides section', var SLIDES_SELECTOR = '.slides section',
HORIZONTAL_SLIDES_SELECTOR = '.slides>section', HORIZONTAL_SLIDES_SELECTOR = '.slides>section',
@ -58,6 +58,9 @@
// Display the page number of the current slide // Display the page number of the current slide
slideNumber: false, slideNumber: false,
// Determine which displays to show the slide number on
showSlideNumber: 'all',
// Push each slide change to the browser history // Push each slide change to the browser history
history: false, history: false,
@ -102,6 +105,12 @@
// Flags if speaker notes should be visible to all viewers // Flags if speaker notes should be visible to all viewers
showNotes: false, showNotes: false,
// Global override for autolaying embedded media (video/audio/iframe)
// - null: Media will only autoplay if data-autoplay is present
// - true: All media will autoplay, regardless of individual setting
// - false: No media will autoplay, regardless of individual setting
autoPlayMedia: null,
// Number of milliseconds between automatically proceeding to the // Number of milliseconds between automatically proceeding to the
// next slide, disabled when set to 0, this value can be overwritten // next slide, disabled when set to 0, this value can be overwritten
// by using a data-autoslide attribute on your slides // by using a data-autoslide attribute on your slides
@ -157,9 +166,19 @@
// to PDF, unlimited by default // to PDF, unlimited by default
pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY, pdfMaxPagesPerSlide: Number.POSITIVE_INFINITY,
// Offset used to reduce the height of content within exported PDF pages.
// This exists to account for environment differences based on how you
// print to PDF. CLI printing options, like phantomjs and wkpdf, can end
// on precisely the total height of the document whereas in-browser
// printing has to end one pixel before.
pdfPageHeightOffset: -1,
// Number of slides away from the current that are visible // Number of slides away from the current that are visible
viewDistance: 3, viewDistance: 3,
// The display mode that will be used to show slides
display: 'block',
// Script dependencies to load // Script dependencies to load
dependencies: [] dependencies: []
@ -605,7 +624,7 @@
slideHeight = slideSize.height; slideHeight = slideSize.height;
// Let the browser know what page size we want to print // Let the browser know what page size we want to print
injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0 0 -1px 0;}' ); injectStyleSheet( '@page{size:'+ pageWidth +'px '+ pageHeight +'px; margin: 0px;}' );
// Limit the size of certain elements to the dimensions of the slide // Limit the size of certain elements to the dimensions of the slide
injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' ); injectStyleSheet( '.reveal section>img, .reveal section>video, .reveal section>iframe{max-width: '+ slideWidth +'px; max-height:'+ slideHeight +'px}' );
@ -614,6 +633,9 @@
document.body.style.width = pageWidth + 'px'; document.body.style.width = pageWidth + 'px';
document.body.style.height = pageHeight + 'px'; document.body.style.height = pageHeight + 'px';
// Make sure stretch elements fit on slide
layoutSlideContents( slideWidth, slideHeight );
// Add each slide's index as attributes on itself, we need these // Add each slide's index as attributes on itself, we need these
// indices to generate slide numbers below // indices to generate slide numbers below
toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) { toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) {
@ -652,7 +674,7 @@
// so that no page ever flows onto another // so that no page ever flows onto another
var page = document.createElement( 'div' ); var page = document.createElement( 'div' );
page.className = 'pdf-page'; page.className = 'pdf-page';
page.style.height = ( pageHeight * numberOfPages ) + 'px'; page.style.height = ( ( pageHeight + config.pdfPageHeightOffset ) * numberOfPages ) + 'px';
slide.parentNode.insertBefore( page, slide ); slide.parentNode.insertBefore( page, slide );
page.appendChild( slide ); page.appendChild( slide );
@ -695,7 +717,7 @@
} }
// Inject slide numbers if `slideNumbers` are enabled // Inject slide numbers if `slideNumbers` are enabled
if( config.slideNumber ) { if( config.slideNumber && /all|print/i.test( config.showSlideNumber ) ) {
var slideNumberH = parseInt( slide.getAttribute( 'data-index-h' ), 10 ) + 1, var slideNumberH = parseInt( slide.getAttribute( 'data-index-h' ), 10 ) + 1,
slideNumberV = parseInt( slide.getAttribute( 'data-index-v' ), 10 ) + 1; slideNumberV = parseInt( slide.getAttribute( 'data-index-v' ), 10 ) + 1;
@ -859,7 +881,7 @@
if( data.background ) { if( data.background ) {
// Auto-wrap image urls in url(...) // Auto-wrap image urls in url(...)
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)$/gi.test( data.background ) ) { if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#]|$)/gi.test( data.background ) ) {
slide.setAttribute( 'data-background-image', data.background ); slide.setAttribute( 'data-background-image', data.background );
} }
else { else {
@ -884,6 +906,7 @@
// Additional and optional background properties // Additional and optional background properties
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize; if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
if( data.backgroundSize ) element.setAttribute( 'data-background-size', data.backgroundSize );
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor; if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat; if( data.backgroundRepeat ) element.style.backgroundRepeat = data.backgroundRepeat;
if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition; if( data.backgroundPosition ) element.style.backgroundPosition = data.backgroundPosition;
@ -977,7 +1000,6 @@
dom.controls.style.display = config.controls ? 'block' : 'none'; dom.controls.style.display = config.controls ? 'block' : 'none';
dom.progress.style.display = config.progress ? 'block' : 'none'; dom.progress.style.display = config.progress ? 'block' : 'none';
dom.slideNumber.style.display = config.slideNumber && !isPrintingPDF() ? 'block' : 'none';
if( config.shuffle ) { if( config.shuffle ) {
shuffle(); shuffle();
@ -1030,10 +1052,11 @@
// Iframe link previews // Iframe link previews
if( config.previewLinks ) { if( config.previewLinks ) {
enablePreviewLinks(); enablePreviewLinks();
disablePreviewLinks( '[data-preview-link=false]' );
} }
else { else {
disablePreviewLinks(); disablePreviewLinks();
enablePreviewLinks( '[data-preview-link]' ); enablePreviewLinks( '[data-preview-link]:not([data-preview-link=false])' );
} }
// Remove existing auto-slide controls // Remove existing auto-slide controls
@ -1060,6 +1083,19 @@
} ); } );
} }
// Slide numbers
var slideNumberDisplay = 'none';
if( config.slideNumber && !isPrintingPDF() ) {
if( config.showSlideNumber === 'all' ) {
slideNumberDisplay = 'block';
}
else if( config.showSlideNumber === 'speaker' && isSpeakerNotes() ) {
slideNumberDisplay = 'block';
}
}
dom.slideNumber.style.display = slideNumberDisplay;
sync(); sync();
} }
@ -1225,7 +1261,7 @@
if( value === 'null' ) return null; if( value === 'null' ) return null;
else if( value === 'true' ) return true; else if( value === 'true' ) return true;
else if( value === 'false' ) return false; else if( value === 'false' ) return false;
else if( value.match( /^\d+$/ ) ) return parseFloat( value ); else if( value.match( /^[\d\.]+$/ ) ) return parseFloat( value );
} }
return value; return value;
@ -1426,7 +1462,7 @@
* target element. * target element.
* *
* remaining height = [ configured parent height ] - [ current parent height ] * remaining height = [ configured parent height ] - [ current parent height ]
* *
* @param {HTMLElement} element * @param {HTMLElement} element
* @param {number} [height] * @param {number} [height]
*/ */
@ -1569,9 +1605,9 @@
/** /**
* Unbind preview frame links. * Unbind preview frame links.
*/ */
function disablePreviewLinks() { function disablePreviewLinks( selector ) {
var anchors = toArray( document.querySelectorAll( 'a' ) ); var anchors = toArray( document.querySelectorAll( selector ? selector : 'a' ) );
anchors.forEach( function( element ) { anchors.forEach( function( element ) {
if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) { if( /^(http|www)/gi.test( element.getAttribute( 'href' ) ) ) {
@ -1628,6 +1664,28 @@
} }
/**
* Open or close help overlay window.
*
* @param {Boolean} [override] Flag which overrides the
* toggle logic and forcibly sets the desired state. True means
* help is open, false means it's closed.
*/
function toggleHelp( override ){
if( typeof override === 'boolean' ) {
override ? showHelp() : closeOverlay();
}
else {
if( dom.overlay ) {
closeOverlay();
}
else {
showHelp();
}
}
}
/** /**
* Opens an overlay window with help material. * Opens an overlay window with help material.
*/ */
@ -1770,6 +1828,10 @@
updateProgress(); updateProgress();
updateParallax(); updateParallax();
if( isOverview() ) {
updateOverview();
}
} }
} }
@ -1985,11 +2047,14 @@
*/ */
function updateOverview() { function updateOverview() {
var vmin = Math.min( window.innerWidth, window.innerHeight );
var scale = Math.max( vmin / 5, 150 ) / vmin;
transformSlides( { transformSlides( {
overview: [ overview: [
'scale('+ scale +')',
'translateX('+ ( -indexh * overviewSlideWidth ) +'px)', 'translateX('+ ( -indexh * overviewSlideWidth ) +'px)',
'translateY('+ ( -indexv * overviewSlideHeight ) +'px)', 'translateY('+ ( -indexv * overviewSlideHeight ) +'px)'
'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)'
].join( ' ' ) ].join( ' ' )
} ); } );
@ -2395,13 +2460,20 @@
updateControls(); updateControls();
updateProgress(); updateProgress();
updateBackground( true );
updateSlideNumber(); updateSlideNumber();
updateSlidesVisibility(); updateSlidesVisibility();
updateBackground( true );
updateNotes(); updateNotes();
formatEmbeddedContent(); formatEmbeddedContent();
startEmbeddedContent( currentSlide );
// Start or stop embedded content depending on global config
if( config.autoPlayMedia === false ) {
stopEmbeddedContent( currentSlide );
}
else {
startEmbeddedContent( currentSlide );
}
if( isOverview() ) { if( isOverview() ) {
layoutOverview(); layoutOverview();
@ -2873,34 +2945,17 @@
} ); } );
// Stop any currently playing video background // Stop content inside of previous backgrounds
if( previousBackground ) { if( previousBackground ) {
var previousVideo = previousBackground.querySelector( 'video' ); stopEmbeddedContent( previousBackground );
if( previousVideo ) previousVideo.pause();
} }
// Start content in the current background
if( currentBackground ) { if( currentBackground ) {
// Start video playback startEmbeddedContent( currentBackground );
var currentVideo = currentBackground.querySelector( 'video' );
if( currentVideo ) {
var startVideo = function() {
currentVideo.currentTime = 0;
currentVideo.play();
currentVideo.removeEventListener( 'loadeddata', startVideo );
};
if( currentVideo.readyState > 1 ) {
startVideo();
}
else {
currentVideo.addEventListener( 'loadeddata', startVideo );
}
}
var backgroundImageURL = currentBackground.style.backgroundImage || ''; var backgroundImageURL = currentBackground.style.backgroundImage || '';
@ -2999,6 +3054,13 @@
} }
/**
* Called when the given slide is within the configured view
* distance. Shows the slide element and loads any content
* that is set to load lazily (data-src).
*
* @param {HTMLElement} slide Slide to show
*/
/** /**
* Called when the given slide is within the configured view * Called when the given slide is within the configured view
* distance. Shows the slide element and loads any content * distance. Shows the slide element and loads any content
@ -3009,7 +3071,7 @@
function showSlide( slide ) { function showSlide( slide ) {
// Show the slide element // Show the slide element
slide.style.display = 'block'; slide.style.display = config.display;
// Media elements with data-src attributes // Media elements with data-src attributes
toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) { toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) {
@ -3067,6 +3129,15 @@
video.muted = true; video.muted = true;
} }
// Inline video playback works (at least in Mobile Safari) as
// long as the video is muted and the `playsinline` attribute is
// present
if( isMobileDevice ) {
video.muted = true;
video.autoplay = true;
video.setAttribute( 'playsinline', '' );
}
// Support comma separated lists of video sources // Support comma separated lists of video sources
backgroundVideo.split( ',' ).forEach( function( source ) { backgroundVideo.split( ',' ).forEach( function( source ) {
video.innerHTML += '<source src="'+ source +'">'; video.innerHTML += '<source src="'+ source +'">';
@ -3077,15 +3148,28 @@
// Iframes // Iframes
else if( backgroundIframe ) { else if( backgroundIframe ) {
var iframe = document.createElement( 'iframe' ); var iframe = document.createElement( 'iframe' );
iframe.setAttribute( 'allowfullscreen', '' );
iframe.setAttribute( 'mozallowfullscreen', '' );
iframe.setAttribute( 'webkitallowfullscreen', '' );
// Only load autoplaying content when the slide is shown to
// avoid having it play in the background
if( /autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) {
iframe.setAttribute( 'data-src', backgroundIframe );
}
else {
iframe.setAttribute( 'src', backgroundIframe ); iframe.setAttribute( 'src', backgroundIframe );
iframe.style.width = '100%'; }
iframe.style.height = '100%';
iframe.style.maxHeight = '100%'; iframe.style.width = '100%';
iframe.style.maxWidth = '100%'; iframe.style.height = '100%';
iframe.style.maxHeight = '100%';
iframe.style.maxWidth = '100%';
background.appendChild( iframe ); background.appendChild( iframe );
} }
} }
} }
} }
@ -3189,11 +3273,12 @@
* Start playback of any embedded content inside of * Start playback of any embedded content inside of
* the given element. * the given element.
* *
* @param {HTMLElement} slide * @param {HTMLElement} element
*/ */
function startEmbeddedContent( element ) { function startEmbeddedContent( element ) {
if( element && !isSpeakerNotes() ) { if( element && !isSpeakerNotes() ) {
// Restart GIFs // Restart GIFs
toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) {
// Setting the same unchanged source like this was confirmed // Setting the same unchanged source like this was confirmed
@ -3207,8 +3292,25 @@
return; return;
} }
if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) { // Prefer an explicit global autoplay setting
el.play(); var autoplay = config.autoPlayMedia;
// If no global setting is available, fall back on the element's
// own autoplay setting
if( typeof autoplay !== 'boolean' ) {
autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' );
}
if( autoplay && typeof el.play === 'function' ) {
if( el.readyState > 1 ) {
startEmbeddedMedia( { target: el } );
}
else {
el.removeEventListener( 'loadeddata', startEmbeddedMedia ); // remove first to avoid dupes
el.addEventListener( 'loadeddata', startEmbeddedMedia );
}
} }
} ); } );
@ -3233,15 +3335,36 @@
el.setAttribute( 'src', el.getAttribute( 'data-src' ) ); el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
} }
} ); } );
} }
} }
/**
* Starts playing an embedded video/audio element after
* it has finished loading.
*
* @param {object} event
*/
function startEmbeddedMedia( event ) {
var isAttachedToDOM = !!closestParent( event.target, 'html' ),
isVisible = !!closestParent( event.target, '.present' );
if( isAttachedToDOM && isVisible ) {
event.target.currentTime = 0;
event.target.play();
}
event.target.removeEventListener( 'loadeddata', startEmbeddedMedia );
}
/** /**
* "Starts" the content of an embedded iframe using the * "Starts" the content of an embedded iframe using the
* postMessage API. * postMessage API.
* *
* @param {object} event - postMessage API event * @param {object} event
*/ */
function startEmbeddedIframe( event ) { function startEmbeddedIframe( event ) {
@ -3249,17 +3372,33 @@
if( iframe && iframe.contentWindow ) { if( iframe && iframe.contentWindow ) {
// YouTube postMessage API var isAttachedToDOM = !!closestParent( event.target, 'html' ),
if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) { isVisible = !!closestParent( event.target, '.present' );
iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
} if( isAttachedToDOM && isVisible ) {
// Vimeo postMessage API
else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) { // Prefer an explicit global autoplay setting
iframe.contentWindow.postMessage( '{"method":"play"}', '*' ); var autoplay = config.autoPlayMedia;
}
// Generic postMessage API // If no global setting is available, fall back on the element's
else { // own autoplay setting
iframe.contentWindow.postMessage( 'slide:start', '*' ); if( typeof autoplay !== 'boolean' ) {
autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' );
}
// YouTube postMessage API
if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {
iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
}
// Vimeo postMessage API
else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {
iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
}
// Generic postMessage API
else {
iframe.contentWindow.postMessage( 'slide:start', '*' );
}
} }
} }
@ -3270,40 +3409,41 @@
* Stop playback of any embedded content inside of * Stop playback of any embedded content inside of
* the targeted slide. * the targeted slide.
* *
* @param {HTMLElement} slide * @param {HTMLElement} element
*/ */
function stopEmbeddedContent( slide ) { function stopEmbeddedContent( element ) {
if( slide && slide.parentNode ) { if( element && element.parentNode ) {
// HTML5 media elements // HTML5 media elements
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) { if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
el.setAttribute('data-paused-by-reveal', '');
el.pause(); el.pause();
} }
} ); } );
// Generic postMessage API for non-lazy loaded iframes // Generic postMessage API for non-lazy loaded iframes
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) { toArray( element.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
el.contentWindow.postMessage( 'slide:stop', '*' ); if( el.contentWindow ) el.contentWindow.postMessage( 'slide:stop', '*' );
el.removeEventListener( 'load', startEmbeddedIframe ); el.removeEventListener( 'load', startEmbeddedIframe );
}); });
// YouTube postMessage API // YouTube postMessage API
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) { toArray( element.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) { if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) {
el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' ); el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
} }
}); });
// Vimeo postMessage API // Vimeo postMessage API
toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) { toArray( element.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) { if( !el.hasAttribute( 'data-ignore' ) && el.contentWindow && typeof el.contentWindow.postMessage === 'function' ) {
el.contentWindow.postMessage( '{"method":"pause"}', '*' ); el.contentWindow.postMessage( '{"method":"pause"}', '*' );
} }
}); });
// Lazy loading iframes // Lazy loading iframes
toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
// Only removing the src doesn't actually unload the frame // Only removing the src doesn't actually unload the frame
// in all browsers (Firefox) so we set it to blank first // in all browsers (Firefox) so we set it to blank first
el.setAttribute( 'src', 'about:blank' ); el.setAttribute( 'src', 'about:blank' );
@ -3546,6 +3686,15 @@
} }
/**
* Retrieves all slides in this presentation.
*/
function getSlides() {
return toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ));
}
/** /**
* Retrieves the total number of slides in this presentation. * Retrieves the total number of slides in this presentation.
* *
@ -3553,7 +3702,7 @@
*/ */
function getTotalSlides() { function getTotalSlides() {
return dom.wrapper.querySelectorAll( SLIDES_SELECTOR + ':not(.stack)' ).length; return getSlides().length;
} }
@ -3900,7 +4049,7 @@
// If there are media elements with data-autoplay, // If there are media elements with data-autoplay,
// automatically set the autoSlide duration to the // automatically set the autoSlide duration to the
// length of that media. Not applicable if the slide // length of that media. Not applicable if the slide
// is divided up into fragments. // is divided up into fragments.
// playbackRate is accounted for in the duration. // playbackRate is accounted for in the duration.
if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) { if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
@ -4113,12 +4262,7 @@
// Check if the pressed key is question mark // Check if the pressed key is question mark
if( event.shiftKey && event.charCode === 63 ) { if( event.shiftKey && event.charCode === 63 ) {
if( dom.overlay ) { toggleHelp();
closeOverlay();
}
else {
showHelp( true );
}
} }
} }
@ -4816,9 +4960,6 @@
navigatePrev: navigatePrev, navigatePrev: navigatePrev,
navigateNext: navigateNext, navigateNext: navigateNext,
// Shows a help overlay with keyboard shortcuts
showHelp: showHelp,
// Forces an update in slide layout // Forces an update in slide layout
layout: layout, layout: layout,
@ -4831,6 +4972,9 @@
// Returns an object with the available fragments as booleans (prev/next) // Returns an object with the available fragments as booleans (prev/next)
availableFragments: availableFragments, availableFragments: availableFragments,
// Toggles a help overlay with keyboard shortcuts
toggleHelp: toggleHelp,
// Toggles the overview mode on/off // Toggles the overview mode on/off
toggleOverview: toggleOverview, toggleOverview: toggleOverview,
@ -4853,12 +4997,19 @@
getState: getState, getState: getState,
setState: setState, setState: setState,
// Presentation progress
getSlidePastCount: getSlidePastCount,
// Presentation progress on range of 0-1 // Presentation progress on range of 0-1
getProgress: getProgress, getProgress: getProgress,
// Returns the indices of the current, or specified, slide // Returns the indices of the current, or specified, slide
getIndices: getIndices, getIndices: getIndices,
// Returns an Array of all slides
getSlides: getSlides,
// Returns the total number of slides
getTotalSlides: getTotalSlides, getTotalSlides: getTotalSlides,
// Returns the slide element at the specified index // Returns the slide element at the specified index

View file

@ -1 +0,0 @@
../../../grunt-cli/bin/grunt

View file

@ -1 +0,0 @@
../../../mustache/bin/mustache

View file

@ -1,13 +1,14 @@
{ {
"name": "reveal.js", "name": "reveal.js",
"version": "3.4.1", "version": "3.5.0",
"description": "The HTML Presentation Framework", "description": "The HTML Presentation Framework",
"homepage": "http://lab.hakim.se/reveal-js", "homepage": "http://lab.hakim.se/reveal-js",
"subdomain": "revealjs", "subdomain": "revealjs",
"main": "js/reveal.js", "main": "js/reveal.js",
"scripts": { "scripts": {
"test": "grunt test", "test": "grunt test",
"start": "grunt serve" "start": "grunt serve",
"build": "grunt"
}, },
"author": { "author": {
"name": "Hakim El Hattab", "name": "Hakim El Hattab",
@ -21,15 +22,11 @@
"engines": { "engines": {
"node": ">=4.0.0" "node": ">=4.0.0"
}, },
"dependencies": {
"express": "~4.14.0",
"grunt-cli": "~1.2.0",
"mustache": "~2.2.1",
"socket.io": "^1.4.8"
},
"devDependencies": { "devDependencies": {
"express": "~4.14.0",
"grunt": "~1.0.1", "grunt": "~1.0.1",
"grunt-autoprefixer": "~3.0.3", "grunt-autoprefixer": "~3.0.3",
"grunt-cli": "~1.2.0",
"grunt-contrib-connect": "~0.11.2", "grunt-contrib-connect": "~0.11.2",
"grunt-contrib-cssmin": "~0.14.0", "grunt-contrib-cssmin": "~0.14.0",
"grunt-contrib-jshint": "~0.11.3", "grunt-contrib-jshint": "~0.11.3",
@ -39,7 +36,9 @@
"grunt-sass": "~1.2.0", "grunt-sass": "~1.2.0",
"grunt-retire": "~0.3.10", "grunt-retire": "~0.3.10",
"grunt-zip": "~0.17.1", "grunt-zip": "~0.17.1",
"node-sass": "~3.13.0" "mustache": "~2.2.1",
"node-sass": "~3.13.0",
"socket.io": "^1.4.8"
}, },
"license": "MIT" "license": "MIT"
} }

View file

@ -31,7 +31,8 @@
*/ */
function getMarkdownFromSlide( section ) { function getMarkdownFromSlide( section ) {
var template = section.querySelector( 'script' ); // look for a <script> or <textarea data-template> wrapper
var template = section.querySelector( '[data-template]' ) || section.querySelector( 'script' );
// strip leading whitespace so it isn't evaluated as code // strip leading whitespace so it isn't evaluated as code
var text = ( template || section ).textContent; var text = ( template || section ).textContent;

View file

@ -7,7 +7,7 @@
var RevealMath = window.RevealMath || (function(){ var RevealMath = window.RevealMath || (function(){
var options = Reveal.getConfig().math || {}; var options = Reveal.getConfig().math || {};
options.mathjax = options.mathjax || 'https://cdn.mathjax.org/mathjax/latest/MathJax.js'; options.mathjax = options.mathjax || 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js';
options.config = options.config || 'TeX-AMS_HTML-full'; options.config = options.config || 'TeX-AMS_HTML-full';
loadScript( options.mathjax + '?config=' + options.config, function() { loadScript( options.mathjax + '?config=' + options.config, function() {

View file

@ -82,6 +82,7 @@
} }
.speaker-controls-time .label, .speaker-controls-time .label,
.speaker-controls-pace .label,
.speaker-controls-notes .label { .speaker-controls-notes .label {
text-transform: uppercase; text-transform: uppercase;
font-weight: normal; font-weight: normal;
@ -90,7 +91,7 @@
margin: 0; margin: 0;
} }
.speaker-controls-time { .speaker-controls-time, .speaker-controls-pace {
border-bottom: 1px solid rgba( 200, 200, 200, 0.5 ); border-bottom: 1px solid rgba( 200, 200, 200, 0.5 );
margin-bottom: 10px; margin-bottom: 10px;
padding: 10px 16px; padding: 10px 16px;
@ -111,6 +112,13 @@
.speaker-controls-time .timer, .speaker-controls-time .timer,
.speaker-controls-time .clock { .speaker-controls-time .clock {
width: 50%; width: 50%;
}
.speaker-controls-time .timer,
.speaker-controls-time .clock,
.speaker-controls-time .pacing .hours-value,
.speaker-controls-time .pacing .minutes-value,
.speaker-controls-time .pacing .seconds-value {
font-size: 1.9em; font-size: 1.9em;
} }
@ -124,7 +132,23 @@
} }
.speaker-controls-time span.mute { .speaker-controls-time span.mute {
color: #bbb; opacity: 0.3;
}
.speaker-controls-time .pacing-title {
margin-top: 5px;
}
.speaker-controls-time .pacing.ahead {
color: blue;
}
.speaker-controls-time .pacing.on-track {
color: green;
}
.speaker-controls-time .pacing.behind {
color: red;
} }
.speaker-controls-notes { .speaker-controls-notes {
@ -276,6 +300,11 @@
<span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span> <span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
<h4 class="label pacing-title" style="display: none">Pacing Time to finish current slide</h4>
<div class="pacing" style="display: none">
<span class="hours-value">00</span><span class="minutes-value">:00</span><span class="seconds-value">:00</span>
</div>
</div> </div>
<div class="speaker-controls-notes hidden"> <div class="speaker-controls-notes hidden">
@ -450,6 +479,47 @@
} }
function getTimings() {
var slides = Reveal.getSlides();
var defaultTiming = Reveal.getConfig().defaultTiming;
if (defaultTiming == null) {
return null;
}
var timings = [];
for ( var i in slides ) {
var slide = slides[i];
var timing = defaultTiming;
if( slide.hasAttribute( 'data-timing' )) {
var t = slide.getAttribute( 'data-timing' );
timing = parseInt(t);
if( isNaN(timing) ) {
console.warn("Could not parse timing '" + t + "' of slide " + i + "; using default of " + defaultTiming);
timing = defaultTiming;
}
}
timings.push(timing);
}
return timings;
}
/**
* Return the number of seconds allocated for presenting
* all slides up to and including this one.
*/
function getTimeAllocated(timings) {
var slides = Reveal.getSlides();
var allocated = 0;
var currentSlide = Reveal.getSlidePastCount();
for (var i in slides.slice(0, currentSlide + 1)) {
allocated += timings[i];
}
return allocated;
}
/** /**
* Create the timer and clock and start updating them * Create the timer and clock and start updating them
* at an interval. * at an interval.
@ -457,28 +527,78 @@
function setupTimer() { function setupTimer() {
var start = new Date(), var start = new Date(),
timeEl = document.querySelector( '.speaker-controls-time' ), timeEl = document.querySelector( '.speaker-controls-time' ),
clockEl = timeEl.querySelector( '.clock-value' ), clockEl = timeEl.querySelector( '.clock-value' ),
hoursEl = timeEl.querySelector( '.hours-value' ), hoursEl = timeEl.querySelector( '.hours-value' ),
minutesEl = timeEl.querySelector( '.minutes-value' ), minutesEl = timeEl.querySelector( '.minutes-value' ),
secondsEl = timeEl.querySelector( '.seconds-value' ); secondsEl = timeEl.querySelector( '.seconds-value' ),
pacingTitleEl = timeEl.querySelector( '.pacing-title' ),
pacingEl = timeEl.querySelector( '.pacing' ),
pacingHoursEl = pacingEl.querySelector( '.hours-value' ),
pacingMinutesEl = pacingEl.querySelector( '.minutes-value' ),
pacingSecondsEl = pacingEl.querySelector( '.seconds-value' );
var timings = getTimings();
if (timings !== null) {
pacingTitleEl.style.removeProperty('display');
pacingEl.style.removeProperty('display');
}
function _displayTime( hrEl, minEl, secEl, time) {
var sign = Math.sign(time) == -1 ? "-" : "";
time = Math.abs(Math.round(time / 1000));
var seconds = time % 60;
var minutes = Math.floor( time / 60 ) % 60 ;
var hours = Math.floor( time / ( 60 * 60 )) ;
hrEl.innerHTML = sign + zeroPadInteger( hours );
if (hours == 0) {
hrEl.classList.add( 'mute' );
}
else {
hrEl.classList.remove( 'mute' );
}
minEl.innerHTML = ':' + zeroPadInteger( minutes );
if (hours == 0 && minutes == 0) {
minEl.classList.add( 'mute' );
}
else {
minEl.classList.remove( 'mute' );
}
secEl.innerHTML = ':' + zeroPadInteger( seconds );
}
function _updateTimer() { function _updateTimer() {
var diff, hours, minutes, seconds, var diff, hours, minutes, seconds,
now = new Date(); now = new Date();
diff = now.getTime() - start.getTime(); diff = now.getTime() - start.getTime();
hours = Math.floor( diff / ( 1000 * 60 * 60 ) );
minutes = Math.floor( ( diff / ( 1000 * 60 ) ) % 60 );
seconds = Math.floor( ( diff / 1000 ) % 60 );
clockEl.innerHTML = now.toLocaleTimeString( 'en-US', { hour12: true, hour: '2-digit', minute:'2-digit' } ); clockEl.innerHTML = now.toLocaleTimeString( 'en-US', { hour12: true, hour: '2-digit', minute:'2-digit' } );
hoursEl.innerHTML = zeroPadInteger( hours ); _displayTime( hoursEl, minutesEl, secondsEl, diff );
hoursEl.className = hours > 0 ? '' : 'mute'; if (timings !== null) {
minutesEl.innerHTML = ':' + zeroPadInteger( minutes ); _updatePacing(diff);
minutesEl.className = minutes > 0 ? '' : 'mute'; }
secondsEl.innerHTML = ':' + zeroPadInteger( seconds );
}
function _updatePacing(diff) {
var slideEndTiming = getTimeAllocated(timings) * 1000;
var currentSlide = Reveal.getSlidePastCount();
var currentSlideTiming = timings[currentSlide] * 1000;
var timeLeftCurrentSlide = slideEndTiming - diff;
if (timeLeftCurrentSlide < 0) {
pacingEl.className = 'pacing behind';
}
else if (timeLeftCurrentSlide < currentSlideTiming) {
pacingEl.className = 'pacing on-track';
}
else {
pacingEl.className = 'pacing ahead';
}
_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
} }
@ -488,9 +608,26 @@
// Then update every second // Then update every second
setInterval( _updateTimer, 1000 ); setInterval( _updateTimer, 1000 );
timeEl.addEventListener( 'click', function() { function _resetTimer() {
start = new Date();
if (timings == null) {
start = new Date();
}
else {
// Reset timer to beginning of current slide
var slideEndTiming = getTimeAllocated(timings) * 1000;
var currentSlide = Reveal.getSlidePastCount();
var currentSlideTiming = timings[currentSlide] * 1000;
var previousSlidesTiming = slideEndTiming - currentSlideTiming;
var now = new Date();
start = new Date(now.getTime() - previousSlidesTiming);
}
_updateTimer(); _updateTimer();
}
timeEl.addEventListener( 'click', function() {
_resetTimer();
return false; return false;
} ); } );

View file

@ -21,6 +21,9 @@ var RevealNotes = (function() {
var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' ); var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' );
// Allow popup window access to Reveal API
notesPopup.Reveal = this.Reveal;
/** /**
* Connect to the notes window through a postmessage handshake. * Connect to the notes window through a postmessage handshake.
* Using postmessage enables us to work in situations where the * Using postmessage enables us to work in situations where the
@ -50,10 +53,11 @@ var RevealNotes = (function() {
/** /**
* Posts the current slide data to the notes window * Posts the current slide data to the notes window
*/ */
function post() { function post( event ) {
var slideElement = Reveal.getCurrentSlide(), var slideElement = Reveal.getCurrentSlide(),
notesElement = slideElement.querySelector( 'aside.notes' ); notesElement = slideElement.querySelector( 'aside.notes' ),
fragmentElement = slideElement.querySelector( '.current-fragment' );
var messageData = { var messageData = {
namespace: 'reveal-notes', namespace: 'reveal-notes',
@ -70,6 +74,21 @@ var RevealNotes = (function() {
messageData.whitespace = 'pre-wrap'; messageData.whitespace = 'pre-wrap';
} }
// Look for notes defined in a fragment
if( fragmentElement ) {
var fragmentNotes = fragmentElement.querySelector( 'aside.notes' );
if( fragmentNotes ) {
notesElement = fragmentNotes;
}
else if( fragmentElement.hasAttribute( 'data-notes' ) ) {
messageData.notes = fragmentElement.getAttribute( 'data-notes' );
messageData.whitespace = 'pre-wrap';
// In case there are slide notes
notesElement = null;
}
}
// Look for notes defined in an aside element // Look for notes defined in an aside element
if( notesElement ) { if( notesElement ) {
messageData.notes = notesElement.innerHTML; messageData.notes = notesElement.innerHTML;

View file

@ -4,30 +4,16 @@
* Example: * Example:
* phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf * phantomjs print-pdf.js "http://lab.hakim.se/reveal-js?print-pdf" reveal-demo.pdf
* *
* By Manuel Bieh (https://github.com/manuelbieh) * @author Manuel Bieh (https://github.com/manuelbieh)
* @author Hakim El Hattab (https://github.com/hakimel)
* @author Manuel Riezebosch (https://github.com/riezebosch)
*/ */
// html2pdf.js // html2pdf.js
var page = new WebPage();
var system = require( 'system' ); var system = require( 'system' );
var slideWidth = system.args[3] ? system.args[3].split( 'x' )[0] : 960; var probePage = new WebPage();
var slideHeight = system.args[3] ? system.args[3].split( 'x' )[1] : 700; var printPage = new WebPage();
page.viewportSize = {
width: slideWidth,
height: slideHeight
};
// TODO
// Something is wrong with these config values. An input
// paper width of 1920px actually results in a 756px wide
// PDF.
page.paperSize = {
width: Math.round( slideWidth * 2 ),
height: Math.round( slideHeight * 2 ),
border: 0
};
var inputFile = system.args[1] || 'index.html?print-pdf'; var inputFile = system.args[1] || 'index.html?print-pdf';
var outputFile = system.args[2] || 'slides.pdf'; var outputFile = system.args[2] || 'slides.pdf';
@ -36,13 +22,48 @@ if( outputFile.match( /\.pdf$/gi ) === null ) {
outputFile += '.pdf'; outputFile += '.pdf';
} }
console.log( 'Printing PDF (Paper size: '+ page.paperSize.width + 'x' + page.paperSize.height +')' ); console.log( 'Export PDF: Reading reveal.js config [1/4]' );
page.open( inputFile, function( status ) { probePage.open( inputFile, function( status ) {
window.setTimeout( function() {
console.log( 'Printed successfully' ); console.log( 'Export PDF: Preparing print layout [2/4]' );
page.render( outputFile );
phantom.exit(); var config = probePage.evaluate( function() {
}, 1000 ); return Reveal.getConfig();
} );
if( config ) {
printPage.paperSize = {
width: Math.floor( config.width * ( 1 + config.margin ) ),
height: Math.floor( config.height * ( 1 + config.margin ) ),
border: 0
};
printPage.open( inputFile, function( status ) {
console.log( 'Export PDF: Preparing pdf [3/4]')
printPage.evaluate(function() {
Reveal.isReady() ? window.callPhantom() : Reveal.addEventListener( 'pdf-ready', window.callPhantom );
});
} );
printPage.onCallback = function(data) {
// For some reason we need to "jump the queue" for syntax highlighting to work.
// See: http://stackoverflow.com/a/3580132/129269
setTimeout(function() {
console.log( 'Export PDF: Writing file [4/4]' );
printPage.render( outputFile );
console.log( 'Export PDF: Finished successfully!' );
phantom.exit();
}, 0);
};
}
else {
console.log( 'Export PDF: Unable to read reveal.js config. Make sure the input address points to a reveal.js page.' );
phantom.exit(1);
}
} ); } );

View file

@ -169,7 +169,7 @@
transition: 'linear', transition: 'linear',
math: { math: {
// mathjax: 'http://cdn.mathjax.org/mathjax/latest/MathJax.js', // mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',
config: 'TeX-AMS_HTML-full' config: 'TeX-AMS_HTML-full'
}, },

View file

@ -13,7 +13,7 @@
<body> <body>
<div id="stash-pane"> <div id="stash-pane">
<div id="controls"> <div id="controls">
<a href="/stash" target="_blank" onclick="save();"> Stash</a> | <a href="/stash" target="_blank" onclick="save();"> Stash</a> |
<a href="/published/{{ .pubTo}}" target="_blank" onclick="save();"> Present</a> | <a href="/published/{{ .pubTo}}" target="_blank" onclick="save();"> Present</a> |
<a href="/published/{{ .pubTo}}?print-pdf" target="_blank" onclick="save();"> Pdf</a> <a href="/published/{{ .pubTo}}?print-pdf" target="_blank" onclick="save();"> Pdf</a>
</div> </div>
@ -33,7 +33,7 @@
</table> </table>
</div> </div>
</div> </div>
<script src="/static/revealjs/js/ace-1.1.8/ace.js" type="text/javascript" charset="utf-8"></script> <script src="/static/revealjs/js/ace-1.1.8/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/revealjs/js/jquery-2.1.3.min.js" type="text/javascript" charset="utf-8"></script> <script src="/static/revealjs/js/jquery-2.1.3.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/revealjs/js/jquery-debounce-1.0.5.js" type="text/javascript" charset="utf-8"></script> <script src="/static/revealjs/js/jquery-debounce-1.0.5.js" type="text/javascript" charset="utf-8"></script>
@ -42,4 +42,4 @@
</body> </body>
</html> </html>
{{ end }} {{ end }}

6
yarn.lock Normal file
View file

@ -0,0 +1,6 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
reveal.js:
version "3.5.0"
resolved "https://registry.yarnpkg.com/reveal.js/-/reveal.js-3.5.0.tgz#95545949ad682636acecfdaea05cf0ca892d442d"