Browse Source

Merge branch 'dev' of github.com:hakimel/reveal.js

Hakim El Hattab 7 years ago
parent
commit
a144134b42

+ 16 - 5
Gruntfile.js

@@ -1,7 +1,9 @@
 /* global module:false */
 module.exports = function(grunt) {
 	var port = grunt.option('port') || 8000;
-	var base = grunt.option('base') || '.';
+	var root = grunt.option('root') || '.';
+
+	if (!Array.isArray(root)) root = [root];
 
 	// Project configuration
 	grunt.initConfig({
@@ -69,6 +71,7 @@ module.exports = function(grunt) {
 				curly: false,
 				eqeqeq: true,
 				immed: true,
+				esnext: true,
 				latedef: true,
 				newcap: true,
 				noarg: true,
@@ -93,11 +96,12 @@ module.exports = function(grunt) {
 			server: {
 				options: {
 					port: port,
-					base: base,
+					base: root,
 					livereload: true,
 					open: true
 				}
-			}
+			},
+
 		},
 
 		zip: {
@@ -126,14 +130,20 @@ module.exports = function(grunt) {
 				tasks: 'css-core'
 			},
 			html: {
-				files: [ '*.html']
+				files: root.map(path => path + '/*.html')
 			},
 			markdown: {
-				files: [ '*.md' ]
+				files: root.map(path => path + '/*.md')
 			},
 			options: {
 				livereload: true
 			}
+		},
+
+		retire: {
+			js: ['js/reveal.js', 'lib/js/*.js', 'plugin/**/*.js'],
+			node: ['.'],
+			options: {}
 		}
 
 	});
@@ -148,6 +158,7 @@ module.exports = function(grunt) {
 	grunt.loadNpmTasks( 'grunt-contrib-connect' );
 	grunt.loadNpmTasks( 'grunt-autoprefixer' );
 	grunt.loadNpmTasks( 'grunt-zip' );
+	grunt.loadNpmTasks( 'grunt-retire' );
 
 	// Default task
 	grunt.registerTask( 'default', [ 'css', 'js' ] );

+ 1 - 1
LICENSE

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

File diff suppressed because it is too large
+ 29 - 8
README.md


+ 3 - 2
css/print/paper.css

@@ -38,7 +38,8 @@
 	.share-reveal,
 	.state-background,
 	.reveal .progress,
-	.reveal .backgrounds {
+	.reveal .backgrounds,
+	.reveal .slide-number {
 		display: none !important;
 	}
 
@@ -199,4 +200,4 @@
 		font-size: 0.8em;
 	}
 
-}
+}

+ 22 - 12
css/print/pdf.css

@@ -60,8 +60,9 @@ ul, ol, div, p {
 }
 .reveal .slides {
 	position: static;
-	width: 100%;
-	height: auto;
+	width: 100% !important;
+	height: auto !important;
+	zoom: 1 !important;
 
 	left: auto;
 	top: auto;
@@ -82,11 +83,16 @@ ul, ol, div, p {
 	        perspective-origin: 50% 50%;
 }
 
+.reveal .slides .pdf-page {
+	position: relative;
+	overflow: hidden;
+	z-index: 1;
+}
+
 .reveal .slides section {
 	page-break-after: always !important;
 
 	visibility: visible !important;
-	position: relative !important;
 	display: block !important;
 	position: relative !important;
 
@@ -132,13 +138,7 @@ ul, ol, div, p {
 	top: 0;
 	left: 0;
 	width: 100%;
-	z-index: -1;
-}
-
-/* All elements should be above the slide-background */
-.reveal section>* {
-	position: relative;
-	z-index: 1;
+	height: 100%;
 }
 
 /* Display slide speaker notes when 'showNotes' is enabled */
@@ -146,15 +146,25 @@ ul, ol, div, p {
 	display: block;
 	width: 100%;
 	max-height: none;
-	left: auto;
 	top: auto;
+	right: auto;
+	bottom: auto;
+	left: auto;
 	z-index: 100;
 }
 
+/* Layout option which makes notes appear on a separate page */
+.reveal .speaker-notes-pdf[data-layout="separate-page"] {
+	position: relative;
+	color: inherit;
+	background-color: transparent;
+	padding: 20px;
+	page-break-after: always;
+}
+
 /* Display slide numbers when 'slideNumber' is enabled */
 .reveal .slide-number-pdf {
 	display: block;
 	position: absolute;
 	font-size: 14px;
 }
-

+ 54 - 14
css/reveal.css

@@ -57,18 +57,18 @@ body {
           transition: all .2s ease; }
   .reveal .slides section .fragment.visible {
     opacity: 1;
-    visibility: visible; }
+    visibility: inherit; }
 
 .reveal .slides section .fragment.grow {
   opacity: 1;
-  visibility: visible; }
+  visibility: inherit; }
   .reveal .slides section .fragment.grow.visible {
     -webkit-transform: scale(1.3);
             transform: scale(1.3); }
 
 .reveal .slides section .fragment.shrink {
   opacity: 1;
-  visibility: visible; }
+  visibility: inherit; }
   .reveal .slides section .fragment.shrink.visible {
     -webkit-transform: scale(0.7);
             transform: scale(0.7); }
@@ -82,21 +82,21 @@ body {
 
 .reveal .slides section .fragment.fade-out {
   opacity: 1;
-  visibility: visible; }
+  visibility: inherit; }
   .reveal .slides section .fragment.fade-out.visible {
     opacity: 0;
     visibility: hidden; }
 
 .reveal .slides section .fragment.semi-fade-out {
   opacity: 1;
-  visibility: visible; }
+  visibility: inherit; }
   .reveal .slides section .fragment.semi-fade-out.visible {
     opacity: 0.5;
-    visibility: visible; }
+    visibility: inherit; }
 
 .reveal .slides section .fragment.strike {
   opacity: 1;
-  visibility: visible; }
+  visibility: inherit; }
   .reveal .slides section .fragment.strike.visible {
     text-decoration: line-through; }
 
@@ -133,7 +133,7 @@ body {
   visibility: hidden; }
   .reveal .slides section .fragment.current-visible.current-fragment {
     opacity: 1;
-    visibility: visible; }
+    visibility: inherit; }
 
 .reveal .slides section .fragment.highlight-red,
 .reveal .slides section .fragment.highlight-current-red,
@@ -142,7 +142,7 @@ body {
 .reveal .slides section .fragment.highlight-blue,
 .reveal .slides section .fragment.highlight-current-blue {
   opacity: 1;
-  visibility: visible; }
+  visibility: inherit; }
 
 .reveal .slides section .fragment.highlight-red.visible {
   color: #ff2c2d; }
@@ -341,8 +341,8 @@ body {
   width: 100%;
   padding: 20px 0px;
   z-index: 10;
-  -webkit-transform-style: preserve-3d;
-          transform-style: preserve-3d;
+  -webkit-transform-style: flat;
+          transform-style: flat;
   -webkit-transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
           transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
 
@@ -463,6 +463,11 @@ body {
  * CONVEX TRANSITION
  * Aliased 'default' for backwards compatibility
  *********************************************/
+.reveal .slides section[data-transition=default].stack,
+.reveal.default .slides section.stack {
+  -webkit-transform-style: preserve-3d;
+          transform-style: preserve-3d; }
+
 .reveal .slides > section[data-transition=default].past,
 .reveal .slides > section[data-transition~=default-out].past,
 .reveal.default .slides > section:not([data-transition]).past {
@@ -487,6 +492,11 @@ body {
   -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
           transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); }
 
+.reveal .slides section[data-transition=convex].stack,
+.reveal.convex .slides section.stack {
+  -webkit-transform-style: preserve-3d;
+          transform-style: preserve-3d; }
+
 .reveal .slides > section[data-transition=convex].past,
 .reveal .slides > section[data-transition~=convex-out].past,
 .reveal.convex .slides > section:not([data-transition]).past {
@@ -514,6 +524,11 @@ body {
 /*********************************************
  * CONCAVE TRANSITION
  *********************************************/
+.reveal .slides section[data-transition=concave].stack,
+.reveal.concave .slides section.stack {
+  -webkit-transform-style: preserve-3d;
+          transform-style: preserve-3d; }
+
 .reveal .slides > section[data-transition=concave].past,
 .reveal .slides > section[data-transition~=concave-out].past,
 .reveal.concave .slides > section:not([data-transition]).past {
@@ -584,7 +599,9 @@ body {
   min-height: 700px;
   -webkit-backface-visibility: hidden;
           backface-visibility: hidden;
-  box-sizing: border-box; }
+  box-sizing: border-box;
+  -webkit-transform-style: preserve-3d;
+          transform-style: preserve-3d; }
 
 .reveal.center.cube .slides section {
   min-height: 0; }
@@ -657,7 +674,9 @@ body {
 .reveal.page .slides section {
   padding: 30px;
   min-height: 700px;
-  box-sizing: border-box; }
+  box-sizing: border-box;
+  -webkit-transform-style: preserve-3d;
+          transform-style: preserve-3d; }
 
 .reveal.page .slides section.past {
   z-index: 12; }
@@ -982,6 +1001,8 @@ body {
           perspective-origin: 50% 50%;
   -webkit-perspective: 700px;
           perspective: 700px; }
+  .reveal.overview .slides {
+    -moz-transform-style: preserve-3d; }
   .reveal.overview .slides section {
     height: 100%;
     top: 0 !important;
@@ -1009,7 +1030,8 @@ body {
     overflow: visible; }
   .reveal.overview .backgrounds {
     -webkit-perspective: inherit;
-            perspective: inherit; }
+            perspective: inherit;
+    -moz-transform-style: preserve-3d; }
   .reveal.overview .backgrounds .slide-background {
     opacity: 1;
     visibility: visible;
@@ -1118,6 +1140,7 @@ body {
   display: inline-block;
   width: 40px;
   height: 40px;
+  line-height: 36px;
   padding: 0 10px;
   float: right;
   opacity: 0.6;
@@ -1166,6 +1189,23 @@ body {
   opacity: 1;
   visibility: visible; }
 
+.reveal .overlay.overlay-preview.loaded .viewport-inner {
+  position: absolute;
+  z-index: -1;
+  left: 0;
+  top: 45%;
+  width: 100%;
+  text-align: center;
+  letter-spacing: normal; }
+
+.reveal .overlay.overlay-preview .x-frame-error {
+  opacity: 0;
+  -webkit-transition: opacity 0.3s ease 0.3s;
+          transition: opacity 0.3s ease 0.3s; }
+
+.reveal .overlay.overlay-preview.loaded .x-frame-error {
+  opacity: 1; }
+
 .reveal .overlay.overlay-preview.loaded .spinner {
   opacity: 0;
   visibility: hidden;

+ 54 - 10
css/reveal.scss

@@ -69,13 +69,13 @@ body {
 
 	&.visible {
 		opacity: 1;
-		visibility: visible;
+		visibility: inherit;
 	}
 }
 
 .reveal .slides section .fragment.grow {
 	opacity: 1;
-	visibility: visible;
+	visibility: inherit;
 
 	&.visible {
 		transform: scale( 1.3 );
@@ -84,7 +84,7 @@ body {
 
 .reveal .slides section .fragment.shrink {
 	opacity: 1;
-	visibility: visible;
+	visibility: inherit;
 
 	&.visible {
 		transform: scale( 0.7 );
@@ -101,7 +101,7 @@ body {
 
 .reveal .slides section .fragment.fade-out {
 	opacity: 1;
-	visibility: visible;
+	visibility: inherit;
 
 	&.visible {
 		opacity: 0;
@@ -111,17 +111,17 @@ body {
 
 .reveal .slides section .fragment.semi-fade-out {
 	opacity: 1;
-	visibility: visible;
+	visibility: inherit;
 
 	&.visible {
 		opacity: 0.5;
-		visibility: visible;
+		visibility: inherit;
 	}
 }
 
 .reveal .slides section .fragment.strike {
 	opacity: 1;
-	visibility: visible;
+	visibility: inherit;
 
 	&.visible {
 		text-decoration: line-through;
@@ -166,7 +166,7 @@ body {
 
 	&.current-fragment {
 		opacity: 1;
-		visibility: visible;
+		visibility: inherit;
 	}
 }
 
@@ -177,7 +177,7 @@ body {
 .reveal .slides section .fragment.highlight-blue,
 .reveal .slides section .fragment.highlight-current-blue {
 	opacity: 1;
-	visibility: visible;
+	visibility: inherit;
 }
 	.reveal .slides section .fragment.highlight-red.visible {
 		color: #ff2c2d
@@ -408,7 +408,7 @@ body {
 	padding: 20px 0px;
 
 	z-index: 10;
-	transform-style: preserve-3d;
+	transform-style: flat;
 	transition: transform-origin 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985),
 				transform 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985),
 				visibility 800ms cubic-bezier(0.260, 0.860, 0.440, 0.985),
@@ -480,6 +480,12 @@ body {
 		@content;
 	}
 }
+@mixin transition-stack($style) {
+	.reveal .slides section[data-transition=#{$style}].stack,
+	.reveal.#{$style} .slides section.stack {
+		@content;
+	}
+}
 @mixin transition-horizontal-past($style) {
 	.reveal .slides>section[data-transition=#{$style}].past,
 	.reveal .slides>section[data-transition~=#{$style}-out].past,
@@ -539,6 +545,10 @@ body {
  *********************************************/
 
 @each $stylename in default, convex {
+	@include transition-stack(#{$stylename}) {
+		transform-style: preserve-3d;
+	}
+
 	@include transition-horizontal-past(#{$stylename}) {
 		transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
 	}
@@ -557,6 +567,10 @@ body {
  * CONCAVE TRANSITION
  *********************************************/
 
+@include transition-stack(concave) {
+	transform-style: preserve-3d;
+}
+
 @include transition-horizontal-past(concave) {
 	transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
 }
@@ -607,6 +621,7 @@ body {
 	min-height: 700px;
 	backface-visibility: hidden;
 	box-sizing: border-box;
+	transform-style: preserve-3d;
 }
 	.reveal.center.cube .slides section {
 		min-height: 0;
@@ -678,6 +693,7 @@ body {
 	padding: 30px;
 	min-height: 700px;
 	box-sizing: border-box;
+	transform-style: preserve-3d;
 }
 	.reveal.page .slides section.past {
 		z-index: 12;
@@ -1012,6 +1028,12 @@ body {
 	perspective-origin: 50% 50%;
 	perspective: 700px;
 
+	.slides {
+		// Fixes overview rendering errors in FF48+, not applied to
+		// other browsers since it degrades performance
+		-moz-transform-style: preserve-3d;
+	}
+
 	.slides section {
 		height: 100%;
 		top: 0 !important;
@@ -1044,6 +1066,10 @@ body {
 
 	.backgrounds {
 		perspective: inherit;
+
+		// Fixes overview rendering errors in FF48+, not applied to
+		// other browsers since it degrades performance
+		-moz-transform-style: preserve-3d;
 	}
 
 	.backgrounds .slide-background {
@@ -1169,6 +1195,7 @@ body {
 			display: inline-block;
 			width: 40px;
 			height: 40px;
+			line-height: 36px;
 			padding: 0 10px;
 			float: right;
 			opacity: 0.6;
@@ -1220,6 +1247,23 @@ body {
 		visibility: visible;
 	}
 
+	.reveal .overlay.overlay-preview.loaded .viewport-inner  {
+		position: absolute;
+		z-index: -1;
+		left: 0;
+		top: 45%;
+		width: 100%;
+		text-align: center;
+		letter-spacing: normal;
+	}
+	.reveal .overlay.overlay-preview .x-frame-error  {
+		opacity: 0;
+		transition: opacity 0.3s ease 0.3s;
+	}
+	.reveal .overlay.overlay-preview.loaded .x-frame-error  {
+		opacity: 1;
+	}
+
 	.reveal .overlay.overlay-preview.loaded .spinner {
 		opacity: 0;
 		visibility: hidden;

+ 6 - 1
css/theme/beige.css

@@ -20,7 +20,7 @@ body {
 
 .reveal {
   font-family: "Lato", sans-serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #333; }
 
@@ -29,6 +29,11 @@ body {
   background: rgba(79, 64, 28, 0.99);
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: rgba(79, 64, 28, 0.99);
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/black.css

@@ -16,7 +16,7 @@ body {
 
 .reveal {
   font-family: "Source Sans Pro", Helvetica, sans-serif;
-  font-size: 38px;
+  font-size: 42px;
   font-weight: normal;
   color: #fff; }
 
@@ -25,6 +25,11 @@ body {
   background: #bee4fd;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #bee4fd;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/blood.css

@@ -19,7 +19,7 @@ body {
 
 .reveal {
   font-family: Ubuntu, "sans-serif";
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #eee; }
 
@@ -28,6 +28,11 @@ body {
   background: #a23;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #a23;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/league.css

@@ -22,7 +22,7 @@ body {
 
 .reveal {
   font-family: "Lato", sans-serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #eee; }
 
@@ -31,6 +31,11 @@ body {
   background: #FF5E99;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #FF5E99;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/moon.css

@@ -20,7 +20,7 @@ body {
 
 .reveal {
   font-family: "Lato", sans-serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #93a1a1; }
 
@@ -29,6 +29,11 @@ body {
   background: #d33682;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #d33682;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/night.css

@@ -14,7 +14,7 @@ body {
 
 .reveal {
   font-family: "Open Sans", sans-serif;
-  font-size: 30px;
+  font-size: 40px;
   font-weight: normal;
   color: #eee; }
 
@@ -23,6 +23,11 @@ body {
   background: #e7ad52;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #e7ad52;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/serif.css

@@ -16,7 +16,7 @@ body {
 
 .reveal {
   font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #000; }
 
@@ -25,6 +25,11 @@ body {
   background: #26351C;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #26351C;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 9 - 1
css/theme/simple.css

@@ -7,6 +7,9 @@
  */
 @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
 @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
+section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 {
+  color: #fff; }
+
 /*********************************************
  * GLOBAL STYLES
  *********************************************/
@@ -16,7 +19,7 @@ body {
 
 .reveal {
   font-family: "Lato", sans-serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #000; }
 
@@ -25,6 +28,11 @@ body {
   background: rgba(0, 0, 0, 0.99);
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: rgba(0, 0, 0, 0.99);
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/sky.css

@@ -23,7 +23,7 @@ body {
 
 .reveal {
   font-family: "Open Sans", sans-serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #333; }
 
@@ -32,6 +32,11 @@ body {
   background: #134674;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #134674;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 6 - 1
css/theme/solarized.css

@@ -20,7 +20,7 @@ body {
 
 .reveal {
   font-family: "Lato", sans-serif;
-  font-size: 36px;
+  font-size: 40px;
   font-weight: normal;
   color: #657b83; }
 
@@ -29,6 +29,11 @@ body {
   background: #d33682;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #d33682;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

+ 1 - 1
css/theme/source/black.scss

@@ -21,7 +21,7 @@ $backgroundColor: #222;
 $mainColor: #fff;
 $headingColor: #fff;
 
-$mainFontSize: 38px;
+$mainFontSize: 42px;
 $mainFont: 'Source Sans Pro', Helvetica, sans-serif;
 $headingFont: 'Source Sans Pro', Helvetica, sans-serif;
 $headingTextShadow: none;

+ 0 - 1
css/theme/source/blood.scss

@@ -28,7 +28,6 @@ $backgroundColor: $coal;
 
 // Main text
 $mainFont: Ubuntu, 'sans-serif';
-$mainFontSize: 36px;
 $mainColor: #eee;
 
 // Headings

+ 0 - 1
css/theme/source/night.scss

@@ -27,7 +27,6 @@ $headingTextShadow: none;
 $headingLetterSpacing: -0.03em;
 $headingTextTransform: none;
 $selectionBackgroundColor: #e7ad52;
-$mainFontSize: 30px;
 
 
 // Theme template ------------------------------

+ 5 - 0
css/theme/source/simple.scss

@@ -31,6 +31,11 @@ $linkColor: #00008B;
 $linkColorHover: lighten( $linkColor, 20% );
 $selectionBackgroundColor: rgba(0, 0, 0, 0.99);
 
+section.has-dark-background {
+	&, h1, h2, h3, h4, h5, h6 {
+		color: #fff;
+	}
+}
 
 
 // Theme template ------------------------------

+ 1 - 1
css/theme/source/white.scss

@@ -21,7 +21,7 @@ $backgroundColor: #fff;
 $mainColor: #222;
 $headingColor: #222;
 
-$mainFontSize: 38px;
+$mainFontSize: 42px;
 $mainFont: 'Source Sans Pro', Helvetica, sans-serif;
 $headingFont: 'Source Sans Pro', Helvetica, sans-serif;
 $headingTextShadow: none;

+ 1 - 1
css/theme/template/settings.scss

@@ -6,7 +6,7 @@ $backgroundColor: #2b2b2b;
 
 // Primary/body text
 $mainFont: 'Lato', sans-serif;
-$mainFontSize: 36px;
+$mainFontSize: 40px;
 $mainColor: #eee;
 
 // Vertical spacing between blocks of text

+ 6 - 0
css/theme/template/theme.scss

@@ -22,6 +22,12 @@ body {
 	text-shadow: none;
 }
 
+::-moz-selection {
+	color: $selectionColor;
+	background: $selectionBackgroundColor;
+	text-shadow: none;
+}
+
 .reveal .slides>section,
 .reveal .slides>section>section {
 	line-height: 1.3;

+ 6 - 1
css/theme/white.css

@@ -16,7 +16,7 @@ body {
 
 .reveal {
   font-family: "Source Sans Pro", Helvetica, sans-serif;
-  font-size: 38px;
+  font-size: 42px;
   font-weight: normal;
   color: #222; }
 
@@ -25,6 +25,11 @@ body {
   background: #98bdef;
   text-shadow: none; }
 
+::-moz-selection {
+  color: #fff;
+  background: #98bdef;
+  text-shadow: none; }
+
 .reveal .slides > section,
 .reveal .slides > section > section {
   line-height: 1.3;

File diff suppressed because it is too large
+ 388 - 171
js/reveal.js


+ 7 - 6
package.json

@@ -22,21 +22,22 @@
     "node": ">=4.0.0"
   },
   "dependencies": {
-    "express": "~4.13.3",
-    "grunt-cli": "~0.1.13",
+    "express": "~4.14.0",
+    "grunt-cli": "~1.2.0",
     "mustache": "~2.2.1",
-    "socket.io": "~1.3.7"
+    "socket.io": "^1.4.8"
   },
   "devDependencies": {
-    "grunt": "~0.4.5",
+    "grunt": "~1.0.1",
     "grunt-autoprefixer": "~3.0.3",
     "grunt-contrib-connect": "~0.11.2",
     "grunt-contrib-cssmin": "~0.14.0",
     "grunt-contrib-jshint": "~0.11.3",
     "grunt-contrib-qunit": "~1.2.0",
     "grunt-contrib-uglify": "~0.9.2",
-    "grunt-contrib-watch": "~0.6.1",
-    "grunt-sass": "~1.1.0-beta",
+    "grunt-contrib-watch": "~1.0.0",
+    "grunt-sass": "~1.2.0",
+    "grunt-retire": "~0.3.10",
     "grunt-zip": "~0.17.1",
     "node-sass": "~3.13.0"
   },

+ 48 - 1
plugin/highlight/highlight.js

@@ -1,5 +1,52 @@
 // START CUSTOM REVEAL.JS INTEGRATION
 (function() {
+	// Function to perform a better "data-trim" on code snippets
+	// Will slice an indentation amount on each line of the snippet (amount based on the line having the lowest indentation length)
+	function betterTrim(snippetEl) {
+		// Helper functions
+		function trimLeft(val) {
+			// Adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
+			return val.replace(/^[\s\uFEFF\xA0]+/g, '');
+		}
+		function trimLineBreaks(input) {
+			var lines = input.split('\n');
+
+			// Trim line-breaks from the beginning
+			for (var i = 0; i < lines.length; i++) {
+				if (lines[i].trim() === '') {
+					lines.splice(i--, 1);
+				} else break;
+			}
+
+			// Trim line-breaks from the end
+			for (var i = lines.length-1; i >= 0; i--) {
+				if (lines[i].trim() === '') {
+					lines.splice(i, 1);
+				} else break;
+			}
+
+			return lines.join('\n');
+		}
+
+		// Main function for betterTrim()
+		return (function(snippetEl) {
+			var content = trimLineBreaks(snippetEl.innerHTML);
+			var lines = content.split('\n');
+			// Calculate the minimum amount to remove on each line start of the snippet (can be 0)
+			var pad = lines.reduce(function(acc, line) {
+				if (line.length > 0 && trimLeft(line).length > 0 && acc > line.length - trimLeft(line).length) {
+					return line.length - trimLeft(line).length;
+				}
+				return acc;
+			}, Number.POSITIVE_INFINITY);
+			// Slice each line with this amount
+			return lines.map(function(line, index) {
+				return line.slice(pad);
+			})
+			.join('\n');
+		})(snippetEl);
+	}
+
 	if( typeof window.addEventListener === 'function' ) {
 		var hljs_nodes = document.querySelectorAll( 'pre code' );
 
@@ -8,7 +55,7 @@
 
 			// trim whitespace if data-trim attribute is present
 			if( element.hasAttribute( 'data-trim' ) && typeof element.innerHTML.trim === 'function' ) {
-				element.innerHTML = element.innerHTML.trim();
+				element.innerHTML = betterTrim(element);
 			}
 
 			// Now escape html unless prevented by author

+ 19 - 13
plugin/markdown/markdown.js

@@ -17,18 +17,6 @@
 	}
 }( this, function( marked ) {
 
-	if( typeof marked === 'undefined' ) {
-		throw 'The reveal.js Markdown plugin requires marked to be loaded';
-	}
-
-	if( typeof hljs !== 'undefined' ) {
-		marked.setOptions({
-			highlight: function( lang, code ) {
-				return hljs.highlightAuto( lang, code ).value;
-			}
-		});
-	}
-
 	var DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$',
 		DEFAULT_NOTES_SEPARATOR = 'note:',
 		DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
@@ -189,7 +177,7 @@
 				markdownSections += '<section '+ options.attributes +'>';
 
 				sectionStack[i].forEach( function( child ) {
-					markdownSections += '<section data-markdown>' +  createMarkdownSlide( child, options ) + '</section>';
+					markdownSections += '<section data-markdown>' + createMarkdownSlide( child, options ) + '</section>';
 				} );
 
 				markdownSections += '</section>';
@@ -391,6 +379,24 @@
 	return {
 
 		initialize: function() {
+			if( typeof marked === 'undefined' ) {
+				throw 'The reveal.js Markdown plugin requires marked to be loaded';
+			}
+
+			if( typeof hljs !== 'undefined' ) {
+				marked.setOptions({
+					highlight: function( code, lang ) {
+						return hljs.highlightAuto( code, [lang] ).value;
+					}
+				});
+			}
+
+			var options = Reveal.getConfig().markdown;
+
+			if ( options ) {
+				marked.setOptions( options );
+			}
+
 			processSlides();
 			convertSlides();
 		},

File diff suppressed because it is too large
+ 1 - 1
plugin/markdown/marked.js


+ 198 - 20
plugin/notes-server/notes.html

@@ -8,6 +8,7 @@
 		<style>
 			body {
 				font-family: Helvetica;
+				font-size: 18px;
 			}
 
 			#current-slide,
@@ -30,15 +31,26 @@
 				position: absolute;
 				top: 10px;
 				left: 10px;
-				font-weight: bold;
-				font-size: 14px;
 				z-index: 2;
-				color: rgba( 255, 255, 255, 0.9 );
+			}
+
+			.overlay-element {
+				height: 34px;
+				line-height: 34px;
+				padding: 0 10px;
+				text-shadow: none;
+				background: rgba( 220, 220, 220, 0.8 );
+				color: #222;
+				font-size: 14px;
+			}
+
+			.overlay-element.interactive:hover {
+				background: rgba( 220, 220, 220, 1 );
 			}
 
 			#current-slide {
 				position: absolute;
-				width: 65%;
+				width: 60%;
 				height: 100%;
 				top: 0;
 				left: 0;
@@ -47,19 +59,20 @@
 
 			#upcoming-slide {
 				position: absolute;
-				width: 35%;
+				width: 40%;
 				height: 40%;
 				right: 0;
 				top: 0;
 			}
 
+			/* Speaker controls */
 			#speaker-controls {
 				position: absolute;
 				top: 40%;
 				right: 0;
-				width: 35%;
+				width: 40%;
 				height: 60%;
-
+				overflow: auto;
 				font-size: 18px;
 			}
 
@@ -124,26 +137,108 @@
 					font-size: 1.2em;
 				}
 
+			/* Layout selector */
+			#speaker-layout {
+				position: absolute;
+				top: 10px;
+				right: 10px;
+				color: #222;
+				z-index: 10;
+			}
+				#speaker-layout select {
+					position: absolute;
+					width: 100%;
+					height: 100%;
+					top: 0;
+					left: 0;
+					border: 0;
+					box-shadow: 0;
+					cursor: pointer;
+					opacity: 0;
+
+					font-size: 1em;
+					background-color: transparent;
+
+					-moz-appearance: none;
+					-webkit-appearance: none;
+					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+				}
+
+				#speaker-layout select:focus {
+					outline: none;
+					box-shadow: none;
+				}
+
 			.clear {
 				clear: both;
 			}
 
-			@media screen and (max-width: 1080px) {
-				#speaker-controls {
-					font-size: 16px;
-				}
+			/* Speaker layout: Wide */
+			body[data-speaker-layout="wide"] #current-slide,
+			body[data-speaker-layout="wide"] #upcoming-slide {
+				width: 50%;
+				height: 45%;
+				padding: 6px;
 			}
 
-			@media screen and (max-width: 900px) {
-				#speaker-controls {
-					font-size: 14px;
-				}
+			body[data-speaker-layout="wide"] #current-slide {
+				top: 0;
+				left: 0;
 			}
 
-			@media screen and (max-width: 800px) {
-				#speaker-controls {
-					font-size: 12px;
-				}
+			body[data-speaker-layout="wide"] #upcoming-slide {
+				top: 0;
+				left: 50%;
+			}
+
+			body[data-speaker-layout="wide"] #speaker-controls {
+				top: 45%;
+				left: 0;
+				width: 100%;
+				height: 50%;
+				font-size: 1.25em;
+			}
+
+			/* Speaker layout: Tall */
+			body[data-speaker-layout="tall"] #current-slide,
+			body[data-speaker-layout="tall"] #upcoming-slide {
+				width: 45%;
+				height: 50%;
+				padding: 6px;
+			}
+
+			body[data-speaker-layout="tall"] #current-slide {
+				top: 0;
+				left: 0;
+			}
+
+			body[data-speaker-layout="tall"] #upcoming-slide {
+				top: 50%;
+				left: 0;
+			}
+
+			body[data-speaker-layout="tall"] #speaker-controls {
+				padding-top: 40px;
+				top: 0;
+				left: 45%;
+				width: 55%;
+				height: 100%;
+				font-size: 1.25em;
+			}
+
+			/* Speaker layout: Notes only */
+			body[data-speaker-layout="notes-only"] #current-slide,
+			body[data-speaker-layout="notes-only"] #upcoming-slide {
+				display: none;
+			}
+
+			body[data-speaker-layout="notes-only"] #speaker-controls {
+				padding-top: 40px;
+				top: 0;
+				left: 0;
+				width: 100%;
+				height: 100%;
+				font-size: 1.25em;
 			}
 
 		</style>
@@ -152,7 +247,7 @@
 	<body>
 
 		<div id="current-slide"></div>
-		<div id="upcoming-slide"><span class="label">UPCOMING:</span></div>
+		<div id="upcoming-slide"><span class="overlay-element label">Upcoming</span></div>
 		<div id="speaker-controls">
 			<div class="speaker-controls-time">
 				<h4 class="label">Time <span class="reset-button">Click to Reset</span></h4>
@@ -170,6 +265,10 @@
 				<div class="value"></div>
 			</div>
 		</div>
+		<div id="speaker-layout" class="overlay-element interactive">
+			<span class="speaker-layout-label"></span>
+			<select class="speaker-layout-dropdown"></select>
+		</div>
 
 		<script src="/socket.io/socket.io.js"></script>
 		<script src="/plugin/markdown/marked.js"></script>
@@ -182,11 +281,20 @@
 				currentState,
 				currentSlide,
 				upcomingSlide,
+				layoutLabel,
+				layoutDropdown,
 				connected = false;
 
 			var socket = io.connect( window.location.origin ),
 				socketId = '{{socketId}}';
 
+			var SPEAKER_LAYOUTS = {
+				'default': 'Default',
+				'wide': 'Wide',
+				'tall': 'Tall',
+				'notes-only': 'Notes only'
+			};
+
 			socket.on( 'statechanged', function( data ) {
 
 				// ignore data from sockets that aren't ours
@@ -205,6 +313,8 @@
 
 			} );
 
+			setupLayout();
+
 			// Load our presentation iframes
 			setupIframes();
 
@@ -362,6 +472,74 @@
 
 			}
 
+			/**
+				 * Sets up the speaker view layout and layout selector.
+				 */
+				function setupLayout() {
+
+					layoutDropdown = document.querySelector( '.speaker-layout-dropdown' );
+					layoutLabel = document.querySelector( '.speaker-layout-label' );
+
+					// Render the list of available layouts
+					for( var id in SPEAKER_LAYOUTS ) {
+						var option = document.createElement( 'option' );
+						option.setAttribute( 'value', id );
+						option.textContent = SPEAKER_LAYOUTS[ id ];
+						layoutDropdown.appendChild( option );
+					}
+
+					// Monitor the dropdown for changes
+					layoutDropdown.addEventListener( 'change', function( event ) {
+
+						setLayout( layoutDropdown.value );
+
+					}, false );
+
+					// Restore any currently persisted layout
+					setLayout( getLayout() );
+
+				}
+
+				/**
+				 * Sets a new speaker view layout. The layout is persisted
+				 * in local storage.
+				 */
+				function setLayout( value ) {
+
+					var title = SPEAKER_LAYOUTS[ value ];
+
+					layoutLabel.innerHTML = 'Layout' + ( title ? ( ': ' + title ) : '' );
+					layoutDropdown.value = value;
+
+					document.body.setAttribute( 'data-speaker-layout', value );
+
+					// Persist locally
+					if( window.localStorage ) {
+						window.localStorage.setItem( 'reveal-speaker-layout', value );
+					}
+
+				}
+
+				/**
+				 * Returns the ID of the most recently set speaker layout
+				 * or our default layout if none has been set.
+				 */
+				function getLayout() {
+
+					if( window.localStorage ) {
+						var layout = window.localStorage.getItem( 'reveal-speaker-layout' );
+						if( layout ) {
+							return layout;
+						}
+					}
+
+					// Default to the first record in the layouts hash
+					for( var id in SPEAKER_LAYOUTS ) {
+						return id;
+					}
+
+				}
+
 			function zeroPadInteger( num ) {
 
 				var str = '00' + parseInt( num );

+ 206 - 11
plugin/notes/notes.html

@@ -8,6 +8,7 @@
 		<style>
 			body {
 				font-family: Helvetica;
+				font-size: 18px;
 			}
 
 			#current-slide,
@@ -30,15 +31,26 @@
 				position: absolute;
 				top: 10px;
 				left: 10px;
-				font-weight: bold;
-				font-size: 14px;
 				z-index: 2;
-				color: rgba( 255, 255, 255, 0.9 );
+			}
+
+			.overlay-element {
+				height: 34px;
+				line-height: 34px;
+				padding: 0 10px;
+				text-shadow: none;
+				background: rgba( 220, 220, 220, 0.8 );
+				color: #222;
+				font-size: 14px;
+			}
+
+			.overlay-element.interactive:hover {
+				background: rgba( 220, 220, 220, 1 );
 			}
 
 			#current-slide {
 				position: absolute;
-				width: 65%;
+				width: 60%;
 				height: 100%;
 				top: 0;
 				left: 0;
@@ -47,20 +59,20 @@
 
 			#upcoming-slide {
 				position: absolute;
-				width: 35%;
+				width: 40%;
 				height: 40%;
 				right: 0;
 				top: 0;
 			}
 
+			/* Speaker controls */
 			#speaker-controls {
 				position: absolute;
 				top: 40%;
 				right: 0;
-				width: 35%;
+				width: 40%;
 				height: 60%;
 				overflow: auto;
-
 				font-size: 18px;
 			}
 
@@ -125,24 +137,124 @@
 					font-size: 1.2em;
 				}
 
+			/* Layout selector */
+			#speaker-layout {
+				position: absolute;
+				top: 10px;
+				right: 10px;
+				color: #222;
+				z-index: 10;
+			}
+				#speaker-layout select {
+					position: absolute;
+					width: 100%;
+					height: 100%;
+					top: 0;
+					left: 0;
+					border: 0;
+					box-shadow: 0;
+					cursor: pointer;
+					opacity: 0;
+
+					font-size: 1em;
+					background-color: transparent;
+
+					-moz-appearance: none;
+					-webkit-appearance: none;
+					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+				}
+
+				#speaker-layout select:focus {
+					outline: none;
+					box-shadow: none;
+				}
+
 			.clear {
 				clear: both;
 			}
 
+			/* Speaker layout: Wide */
+			body[data-speaker-layout="wide"] #current-slide,
+			body[data-speaker-layout="wide"] #upcoming-slide {
+				width: 50%;
+				height: 45%;
+				padding: 6px;
+			}
+
+			body[data-speaker-layout="wide"] #current-slide {
+				top: 0;
+				left: 0;
+			}
+
+			body[data-speaker-layout="wide"] #upcoming-slide {
+				top: 0;
+				left: 50%;
+			}
+
+			body[data-speaker-layout="wide"] #speaker-controls {
+				top: 45%;
+				left: 0;
+				width: 100%;
+				height: 50%;
+				font-size: 1.25em;
+			}
+
+			/* Speaker layout: Tall */
+			body[data-speaker-layout="tall"] #current-slide,
+			body[data-speaker-layout="tall"] #upcoming-slide {
+				width: 45%;
+				height: 50%;
+				padding: 6px;
+			}
+
+			body[data-speaker-layout="tall"] #current-slide {
+				top: 0;
+				left: 0;
+			}
+
+			body[data-speaker-layout="tall"] #upcoming-slide {
+				top: 50%;
+				left: 0;
+			}
+
+			body[data-speaker-layout="tall"] #speaker-controls {
+				padding-top: 40px;
+				top: 0;
+				left: 45%;
+				width: 55%;
+				height: 100%;
+				font-size: 1.25em;
+			}
+
+			/* Speaker layout: Notes only */
+			body[data-speaker-layout="notes-only"] #current-slide,
+			body[data-speaker-layout="notes-only"] #upcoming-slide {
+				display: none;
+			}
+
+			body[data-speaker-layout="notes-only"] #speaker-controls {
+				padding-top: 40px;
+				top: 0;
+				left: 0;
+				width: 100%;
+				height: 100%;
+				font-size: 1.25em;
+			}
+
 			@media screen and (max-width: 1080px) {
-				#speaker-controls {
+				body[data-speaker-layout="default"] #speaker-controls {
 					font-size: 16px;
 				}
 			}
 
 			@media screen and (max-width: 900px) {
-				#speaker-controls {
+				body[data-speaker-layout="default"] #speaker-controls {
 					font-size: 14px;
 				}
 			}
 
 			@media screen and (max-width: 800px) {
-				#speaker-controls {
+				body[data-speaker-layout="default"] #speaker-controls {
 					font-size: 12px;
 				}
 			}
@@ -153,7 +265,7 @@
 	<body>
 
 		<div id="current-slide"></div>
-		<div id="upcoming-slide"><span class="label">UPCOMING:</span></div>
+		<div id="upcoming-slide"><span class="overlay-element label">Upcoming</span></div>
 		<div id="speaker-controls">
 			<div class="speaker-controls-time">
 				<h4 class="label">Time <span class="reset-button">Click to Reset</span></h4>
@@ -171,6 +283,10 @@
 				<div class="value"></div>
 			</div>
 		</div>
+		<div id="speaker-layout" class="overlay-element interactive">
+			<span class="speaker-layout-label"></span>
+			<select class="speaker-layout-dropdown"></select>
+		</div>
 
 		<script src="../../plugin/markdown/marked.js"></script>
 		<script>
@@ -182,8 +298,19 @@
 					currentState,
 					currentSlide,
 					upcomingSlide,
+					layoutLabel,
+					layoutDropdown,
 					connected = false;
 
+				var SPEAKER_LAYOUTS = {
+					'default': 'Default',
+					'wide': 'Wide',
+					'tall': 'Tall',
+					'notes-only': 'Notes only'
+				};
+
+				setupLayout();
+
 				window.addEventListener( 'message', function( event ) {
 
 					var data = JSON.parse( event.data );
@@ -369,6 +496,74 @@
 
 				}
 
+				/**
+				 * Sets up the speaker view layout and layout selector.
+				 */
+				function setupLayout() {
+
+					layoutDropdown = document.querySelector( '.speaker-layout-dropdown' );
+					layoutLabel = document.querySelector( '.speaker-layout-label' );
+
+					// Render the list of available layouts
+					for( var id in SPEAKER_LAYOUTS ) {
+						var option = document.createElement( 'option' );
+						option.setAttribute( 'value', id );
+						option.textContent = SPEAKER_LAYOUTS[ id ];
+						layoutDropdown.appendChild( option );
+					}
+
+					// Monitor the dropdown for changes
+					layoutDropdown.addEventListener( 'change', function( event ) {
+
+						setLayout( layoutDropdown.value );
+
+					}, false );
+
+					// Restore any currently persisted layout
+					setLayout( getLayout() );
+
+				}
+
+				/**
+				 * Sets a new speaker view layout. The layout is persisted
+				 * in local storage.
+				 */
+				function setLayout( value ) {
+
+					var title = SPEAKER_LAYOUTS[ value ];
+
+					layoutLabel.innerHTML = 'Layout' + ( title ? ( ': ' + title ) : '' );
+					layoutDropdown.value = value;
+
+					document.body.setAttribute( 'data-speaker-layout', value );
+
+					// Persist locally
+					if( window.localStorage ) {
+						window.localStorage.setItem( 'reveal-speaker-layout', value );
+					}
+
+				}
+
+				/**
+				 * Returns the ID of the most recently set speaker layout
+				 * or our default layout if none has been set.
+				 */
+				function getLayout() {
+
+					if( window.localStorage ) {
+						var layout = window.localStorage.getItem( 'reveal-speaker-layout' );
+						if( layout ) {
+							return layout;
+						}
+					}
+
+					// Default to the first record in the layouts hash
+					for( var id in SPEAKER_LAYOUTS ) {
+						return id;
+					}
+
+				}
+
 				function zeroPadInteger( num ) {
 
 					var str = '00' + parseInt( num );

+ 11 - 1
plugin/zoom-js/zoom.js

@@ -11,7 +11,17 @@
 		if( event[ modifier ] && isEnabled ) {
 			event.preventDefault();
 
-			var bounds = event.target.getBoundingClientRect();
+			var bounds;
+			var originalDisplay = event.target.style.display;
+
+			// Get the bounding rect of the contents, not the containing box
+			if( window.getComputedStyle( event.target ).display === 'block' ) {
+				event.target.style.display = 'inline-block';
+				bounds = event.target.getBoundingClientRect();
+				event.target.style.display = originalDisplay;
+			} else {
+				bounds = event.target.getBoundingClientRect();
+			}
 
 			zoom.to({
 				x: ( bounds.left * revealScale ) - zoomPadding,

+ 12 - 0
test/simple.md

@@ -0,0 +1,12 @@
+## Slide 1.1
+
+```js
+var a = 1;
+```
+
+
+## Slide 1.2
+
+
+
+## Slide 2

+ 36 - 0
test/test-markdown-external.html

@@ -0,0 +1,36 @@
+<!doctype html>
+<html lang="en">
+
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Test Markdown</title>
+
+		<link rel="stylesheet" href="../css/reveal.css">
+		<link rel="stylesheet" href="qunit-1.12.0.css">
+	</head>
+
+	<body style="overflow: auto;">
+
+		<div id="qunit"></div>
+  		<div id="qunit-fixture"></div>
+
+		<div class="reveal" style="display: none;">
+
+			<div class="slides">
+				<section data-markdown="simple.md" data-separator="^\n\n\n" data-separator-vertical="^\n\n"></section>
+			</div>
+
+		</div>
+
+		<script src="../lib/js/head.min.js"></script>
+		<script src="../js/reveal.js"></script>
+		<script src="../plugin/highlight/highlight.js"></script>
+		<script src="../plugin/markdown/marked.js"></script>
+		<script src="../plugin/markdown/markdown.js"></script>
+		<script src="qunit-1.12.0.js"></script>
+
+		<script src="test-markdown-external.js"></script>
+
+	</body>
+</html>

+ 24 - 0
test/test-markdown-external.js

@@ -0,0 +1,24 @@
+
+
+Reveal.addEventListener( 'ready', function() {
+
+	QUnit.module( 'Markdown' );
+
+	test( 'Vertical separator', function() {
+		strictEqual( document.querySelectorAll( '.reveal .slides>section>section' ).length, 2, 'found two slides' );
+	});
+
+	test( 'Horizontal separator', function() {
+		strictEqual( document.querySelectorAll( '.reveal .slides>section' ).length, 2, 'found two slides' );
+	});
+
+	test( 'Language highlighter', function() {
+		strictEqual( document.querySelectorAll( '.hljs-keyword' ).length, 1, 'got rendered highlight tag.' );
+		strictEqual( document.querySelector( '.hljs-keyword' ).innerHTML, 'var', 'the same keyword: var.' );
+	});
+
+
+} );
+
+Reveal.initialize();
+

+ 41 - 0
test/test-markdown-options.html

@@ -0,0 +1,41 @@
+<!doctype html>
+<html lang="en">
+
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Test Markdown Options</title>
+
+		<link rel="stylesheet" href="../css/reveal.css">
+		<link rel="stylesheet" href="qunit-1.12.0.css">
+	</head>
+
+	<body style="overflow: auto;">
+
+		<div id="qunit"></div>
+		<div id="qunit-fixture"></div>
+
+		<div class="reveal" style="display: none;">
+
+			<div class="slides">
+
+				<section data-markdown>
+					<script type="text/template">
+						## Testing Markdown Options
+
+						This "slide" should contain 'smart' quotes.
+					</script>
+				</section>
+
+			</div>
+
+		</div>
+
+		<script src="../lib/js/head.min.js"></script>
+		<script src="../js/reveal.js"></script>
+		<script src="qunit-1.12.0.js"></script>
+
+		<script src="test-markdown-options.js"></script>
+
+	</body>
+</html>

+ 26 - 0
test/test-markdown-options.js

@@ -0,0 +1,26 @@
+Reveal.addEventListener( 'ready', function() {
+
+	QUnit.module( 'Markdown' );
+
+	test( 'Options are set', function() {
+		strictEqual( marked.defaults.smartypants, true );
+	});
+
+	test( 'Smart quotes are activated', function() {
+		var text = document.querySelector( '.reveal .slides>section>p' ).textContent;
+
+		strictEqual( /['"]/.test( text ), false );
+		strictEqual( /[“”‘’]/.test( text ), true );
+	});
+
+} );
+
+Reveal.initialize({
+	dependencies: [
+		{ src: '../plugin/markdown/marked.js' },
+		{ src: '../plugin/markdown/markdown.js' },
+	],
+	markdown: {
+		smartypants: true
+	}
+});

+ 1 - 1
test/test-markdown.html

@@ -13,7 +13,7 @@
 	<body style="overflow: auto;">
 
 		<div id="qunit"></div>
-  		<div id="qunit-fixture"></div>
+		<div id="qunit-fixture"></div>
 
 		<div class="reveal" style="display: none;">