Explorar el Código

Merge remote-tracking branch 'upstream/master'

Chris Lawrence hace 11 años
padre
commit
55f220109c

+ 2 - 2
Gruntfile.js

@@ -1,6 +1,6 @@
 /* global module:false */
 module.exports = function(grunt) {
-
+	var port = grunt.option('port') || 8000;
 	// Project configuration
 	grunt.initConfig({
 		pkg: grunt.file.readJSON('package.json'),
@@ -78,7 +78,7 @@ module.exports = function(grunt) {
 		connect: {
 			server: {
 				options: {
-					port: 8000,
+					port: port,
 					base: '.'
 				}
 			}

+ 19 - 0
README.md

@@ -778,6 +778,8 @@ $ grunt serve
 
 8. Open <http://localhost:8000> to view your presentation
 
+You can change the port by using `grunt serve --port 8001`.
+
 
 ### Folder Structure
 - **css/** Core styles without which the project does not function
@@ -786,6 +788,23 @@ $ grunt serve
 - **lib/** All other third party assets (JavaScript, CSS, fonts)
 
 
+### Contributing
+
+Please keep the [issue tracker](github.com/hakimel/reveal.js/issues) limited to **bug reports**, **feature requests** and **pull requests**. If you are reporting a bug make sure to include information about which browser and operating system you are using as well as the necessary steps to reproduce the issue.
+
+If you have personal support questions use [StackOverflow](http://stackoverflow.com/questions/tagged/reveal.js).
+
+
+#### Pull requests
+
+- Should follow the coding style
+  - Tabs to indent
+  - Single-quoted strings
+  - No space between function name and opening argument parenthesis
+  - One space after opening and before closing parenthesis 
+- Should be made towards the **dev branch**
+- Should be submitted from a feature/topic branch (not your master)
+
 
 ## License
 

+ 6 - 2
css/reveal.css

@@ -517,6 +517,10 @@ body {
 	        perspective-origin: 0px -100px;
 }
 
+.reveal .slides>section {
+	-ms-perspective: 600px;
+}
+
 .reveal .slides>section,
 .reveal .slides>section>section {
 	display: none;
@@ -1050,8 +1054,8 @@ body {
 
 .reveal.fade.overview .slides section,
 .reveal.fade.overview .slides>section>section,
-.reveal.fade.exit-overview .slides section,
-.reveal.fade.exit-overview .slides>section>section {
+.reveal.fade.overview-deactivating .slides section,
+.reveal.fade.overview-deactivating .slides>section>section {
 	-webkit-transition: none;
 	   -moz-transition: none;
 	    -ms-transition: none;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
css/reveal.min.css


+ 7 - 4
index.html

@@ -167,12 +167,15 @@
 					<h2>Themes</h2>
 					<p>
 						Reveal.js comes with a few themes built in: <br>
+						<a href="?#/themes">Default</a> -
 						<a href="?theme=sky#/themes">Sky</a> -
 						<a href="?theme=beige#/themes">Beige</a> -
 						<a href="?theme=simple#/themes">Simple</a> -
 						<a href="?theme=serif#/themes">Serif</a> -
-						<a href="?theme=night#/themes">Night</a> -
-						<a href="?#/themes">Default</a>
+						<a href="?theme=night#/themes">Night</a> <br>
+						<a href="?theme=moon.css#/themes">Moon</a> -
+						<a href="?theme=simple.css#/themes">Simple</a> -
+						<a href="?theme=solarized.css#/themes">Solarized</a>
 					</p>
 					<p>
 						<small>
@@ -259,10 +262,10 @@ function linkify( selector ) {
     for( var i = 0, len = nodes.length; i &lt; len; i++ ) {
       var node = nodes[i];
 
-      if( !node.className ) ) {
+      if( !node.className ) {
         node.className += ' roll';
       }
-    };
+    }
   }
 }
 					</code></pre>

+ 75 - 91
js/reveal.js

@@ -74,6 +74,9 @@ var Reveal = (function(){
 			// Apply a 3D roll to links on hover
 			rollingLinks: false,
 
+			// Hides the address bar on mobile devices
+			hideAddressBar: true,
+
 			// Opens links in an iframe preview overlay
 			previewLinks: false,
 
@@ -353,17 +356,15 @@ var Reveal = (function(){
 		createSingletonNode( dom.wrapper, 'div', 'pause-overlay', null );
 
 		// Cache references to elements
-		if ( config.controls ) {
-			dom.controls = document.querySelector( '.reveal .controls' );
+		dom.controls = document.querySelector( '.reveal .controls' );
 
-			// There can be multiple instances of controls throughout the page
-			dom.controlsLeft = toArray( document.querySelectorAll( '.navigate-left' ) );
-			dom.controlsRight = toArray( document.querySelectorAll( '.navigate-right' ) );
-			dom.controlsUp = toArray( document.querySelectorAll( '.navigate-up' ) );
-			dom.controlsDown = toArray( document.querySelectorAll( '.navigate-down' ) );
-			dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) );
-			dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) );
-		}
+		// There can be multiple instances of controls throughout the page
+		dom.controlsLeft = toArray( document.querySelectorAll( '.navigate-left' ) );
+		dom.controlsRight = toArray( document.querySelectorAll( '.navigate-right' ) );
+		dom.controlsUp = toArray( document.querySelectorAll( '.navigate-up' ) );
+		dom.controlsDown = toArray( document.querySelectorAll( '.navigate-down' ) );
+		dom.controlsPrev = toArray( document.querySelectorAll( '.navigate-prev' ) );
+		dom.controlsNext = toArray( document.querySelectorAll( '.navigate-next' ) );
 
 	}
 
@@ -491,13 +492,8 @@ var Reveal = (function(){
 		dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
 		dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
 
-		if( dom.controls ) {
-			dom.controls.style.display = ( config.controls && dom.controls ) ? 'block' : 'none';
-		}
-
-		if( dom.progress ) {
-			dom.progress.style.display = ( config.progress && dom.progress ) ? 'block' : 'none';
-		}
+		dom.controls.style.display = config.controls ? 'block' : 'none';
+		dom.progress.style.display = config.progress ? 'block' : 'none';
 
 		if( config.rtl ) {
 			dom.wrapper.classList.add( 'rtl' );
@@ -586,16 +582,14 @@ var Reveal = (function(){
 			dom.progress.addEventListener( 'click', onProgressClicked, false );
 		}
 
-		if ( config.controls && dom.controls ) {
-			[ 'touchstart', 'click' ].forEach( function( eventName ) {
-				dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } );
-				dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } );
-				dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } );
-				dom.controlsDown.forEach( function( el ) { el.addEventListener( eventName, onNavigateDownClicked, false ); } );
-				dom.controlsPrev.forEach( function( el ) { el.addEventListener( eventName, onNavigatePrevClicked, false ); } );
-				dom.controlsNext.forEach( function( el ) { el.addEventListener( eventName, onNavigateNextClicked, false ); } );
-			} );
-		}
+		[ 'touchstart', 'click' ].forEach( function( eventName ) {
+			dom.controlsLeft.forEach( function( el ) { el.addEventListener( eventName, onNavigateLeftClicked, false ); } );
+			dom.controlsRight.forEach( function( el ) { el.addEventListener( eventName, onNavigateRightClicked, false ); } );
+			dom.controlsUp.forEach( function( el ) { el.addEventListener( eventName, onNavigateUpClicked, false ); } );
+			dom.controlsDown.forEach( function( el ) { el.addEventListener( eventName, onNavigateDownClicked, false ); } );
+			dom.controlsPrev.forEach( function( el ) { el.addEventListener( eventName, onNavigatePrevClicked, false ); } );
+			dom.controlsNext.forEach( function( el ) { el.addEventListener( eventName, onNavigateNextClicked, false ); } );
+		} );
 
 	}
 
@@ -624,16 +618,14 @@ var Reveal = (function(){
 			dom.progress.removeEventListener( 'click', onProgressClicked, false );
 		}
 
-		if ( config.controls && dom.controls ) {
-			[ 'touchstart', 'click' ].forEach( function( eventName ) {
-				dom.controlsLeft.forEach( function( el ) { el.removeEventListener( eventName, onNavigateLeftClicked, false ); } );
-				dom.controlsRight.forEach( function( el ) { el.removeEventListener( eventName, onNavigateRightClicked, false ); } );
-				dom.controlsUp.forEach( function( el ) { el.removeEventListener( eventName, onNavigateUpClicked, false ); } );
-				dom.controlsDown.forEach( function( el ) { el.removeEventListener( eventName, onNavigateDownClicked, false ); } );
-				dom.controlsPrev.forEach( function( el ) { el.removeEventListener( eventName, onNavigatePrevClicked, false ); } );
-				dom.controlsNext.forEach( function( el ) { el.removeEventListener( eventName, onNavigateNextClicked, false ); } );
-			} );
-		}
+		[ 'touchstart', 'click' ].forEach( function( eventName ) {
+			dom.controlsLeft.forEach( function( el ) { el.removeEventListener( eventName, onNavigateLeftClicked, false ); } );
+			dom.controlsRight.forEach( function( el ) { el.removeEventListener( eventName, onNavigateRightClicked, false ); } );
+			dom.controlsUp.forEach( function( el ) { el.removeEventListener( eventName, onNavigateUpClicked, false ); } );
+			dom.controlsDown.forEach( function( el ) { el.removeEventListener( eventName, onNavigateDownClicked, false ); } );
+			dom.controlsPrev.forEach( function( el ) { el.removeEventListener( eventName, onNavigatePrevClicked, false ); } );
+			dom.controlsNext.forEach( function( el ) { el.removeEventListener( eventName, onNavigateNextClicked, false ); } );
+		} );
 
 	}
 
@@ -778,7 +770,7 @@ var Reveal = (function(){
 	 */
 	function hideAddressBar() {
 
-		if( /iphone|ipod|android/gi.test( navigator.userAgent ) && !/crios/gi.test( navigator.userAgent ) ) {
+		if( config.hideAddressBar && isMobileDevice ) {
 			// Events that should trigger the address bar to hide
 			window.addEventListener( 'load', removeAddressBar, false );
 			window.addEventListener( 'orientationchange', removeAddressBar, false );
@@ -792,7 +784,8 @@ var Reveal = (function(){
 	 */
 	function removeAddressBar() {
 
-		if( window.orientation === 0 ) {
+		// Portrait and not Chrome for iOS
+		if( window.orientation === 0 && !/crios/gi.test( navigator.userAgent ) ) {
 			document.documentElement.style.overflow = 'scroll';
 			document.body.style.height = '120%';
 		}
@@ -1156,7 +1149,7 @@ var Reveal = (function(){
 			var depth = window.innerWidth < 400 ? 1000 : 2500;
 
 			dom.wrapper.classList.add( 'overview' );
-			dom.wrapper.classList.remove( 'exit-overview' );
+			dom.wrapper.classList.remove( 'overview-deactivating' );
 
 			clearTimeout( activateOverviewTimeout );
 			clearTimeout( deactivateOverviewTimeout );
@@ -1164,7 +1157,7 @@ var Reveal = (function(){
 			// Not the pretties solution, but need to let the overview
 			// class apply first so that slides are measured accurately
 			// before we can position them
-			activateOverviewTimeout = setTimeout( function(){
+			activateOverviewTimeout = setTimeout( function() {
 
 				var horizontalSlides = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR );
 
@@ -1241,25 +1234,19 @@ var Reveal = (function(){
 			// Temporarily add a class so that transitions can do different things
 			// depending on whether they are exiting/entering overview, or just
 			// moving from slide to slide
-			dom.wrapper.classList.add( 'exit-overview' );
+			dom.wrapper.classList.add( 'overview-deactivating' );
 
 			deactivateOverviewTimeout = setTimeout( function () {
-				dom.wrapper.classList.remove( 'exit-overview' );
-			}, 10);
+				dom.wrapper.classList.remove( 'overview-deactivating' );
+			}, 1 );
 
 			// Select all slides
-			var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
-
-			for( var i = 0, len = slides.length; i < len; i++ ) {
-				var element = slides[i];
-
-				element.style.display = '';
-
+			toArray( document.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
 				// Resets all transforms to use the external styles
-				transformElement( element, '' );
+				transformElement( slide, '' );
 
-				element.removeEventListener( 'click', onOverviewSlideClicked, true );
-			}
+				slide.removeEventListener( 'click', onOverviewSlideClicked, true );
+			} );
 
 			slide( indexh, indexv );
 
@@ -1792,48 +1779,45 @@ var Reveal = (function(){
 	 */
 	function updateControls() {
 
-		if ( config.controls && dom.controls ) {
-
-			var routes = availableRoutes();
-			var fragments = availableFragments();
-
-			// Remove the 'enabled' class from all directions
-			dom.controlsLeft.concat( dom.controlsRight )
-							.concat( dom.controlsUp )
-							.concat( dom.controlsDown )
-							.concat( dom.controlsPrev )
-							.concat( dom.controlsNext ).forEach( function( node ) {
-				node.classList.remove( 'enabled' );
-				node.classList.remove( 'fragmented' );
-			} );
+		var routes = availableRoutes();
+		var fragments = availableFragments();
+
+		// Remove the 'enabled' class from all directions
+		dom.controlsLeft.concat( dom.controlsRight )
+						.concat( dom.controlsUp )
+						.concat( dom.controlsDown )
+						.concat( dom.controlsPrev )
+						.concat( dom.controlsNext ).forEach( function( node ) {
+			node.classList.remove( 'enabled' );
+			node.classList.remove( 'fragmented' );
+		} );
 
-			// Add the 'enabled' class to the available routes
-			if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' );	} );
-			if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); } );
-			if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' );	} );
-			if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); } );
+		// Add the 'enabled' class to the available routes
+		if( routes.left ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'enabled' );	} );
+		if( routes.right ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'enabled' ); } );
+		if( routes.up ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'enabled' );	} );
+		if( routes.down ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'enabled' ); } );
 
-			// Prev/next buttons
-			if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); } );
-			if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); } );
+		// Prev/next buttons
+		if( routes.left || routes.up ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'enabled' ); } );
+		if( routes.right || routes.down ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'enabled' ); } );
 
-			// Highlight fragment directions
-			if( currentSlide ) {
+		// Highlight fragment directions
+		if( currentSlide ) {
 
-				// Always apply fragment decorator to prev/next buttons
-				if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
-				if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
+			// Always apply fragment decorator to prev/next buttons
+			if( fragments.prev ) dom.controlsPrev.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
+			if( fragments.next ) dom.controlsNext.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
 
-				// Apply fragment decorators to directional buttons based on
-				// what slide axis they are in
-				if( isVerticalSlide( currentSlide ) ) {
-					if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
-					if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
-				}
-				else {
-					if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
-					if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
-				}
+			// Apply fragment decorators to directional buttons based on
+			// what slide axis they are in
+			if( isVerticalSlide( currentSlide ) ) {
+				if( fragments.prev ) dom.controlsUp.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
+				if( fragments.next ) dom.controlsDown.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
+			}
+			else {
+				if( fragments.prev ) dom.controlsLeft.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
+				if( fragments.next ) dom.controlsRight.forEach( function( el ) { el.classList.add( 'fragmented', 'enabled' ); } );
 			}
 
 		}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
js/reveal.min.js


+ 16 - 17
lib/css/zenburn.css

@@ -13,11 +13,13 @@ pre code {
 
 pre .keyword,
 pre .tag,
-pre .django .tag,
-pre .django .keyword,
 pre .css .class,
 pre .css .id,
-pre .lisp .title {
+pre .lisp .title,
+pre .nginx .title,
+pre .request,
+pre .status,
+pre .clojure .attribute {
   color: #E3CEAB;
 }
 
@@ -49,32 +51,27 @@ pre .tex .special {
 }
 
 pre .diff .chunk,
-pre .ruby .subst {
+pre .subst {
   color: #8F8F8F;
 }
 
 pre .dos .keyword,
 pre .python .decorator,
-pre .class .title,
-pre .haskell .label,
-pre .function .title,
-pre .ini .title,
+pre .title,
+pre .haskell .type,
 pre .diff .header,
 pre .ruby .class .parent,
 pre .apache .tag,
 pre .nginx .built_in,
 pre .tex .command,
-pre .input_number {
+pre .prompt {
     color: #efef8f;
 }
 
 pre .dos .winutils,
 pre .ruby .symbol,
 pre .ruby .symbol .string,
-pre .ruby .symbol .keyword,
-pre .ruby .symbol .keymethods,
-pre .ruby .string,
-pre .ruby .instancevar {
+pre .ruby .string {
   color: #DCA3A3;
 }
 
@@ -106,10 +103,12 @@ pre .doctype {
   color: #7F9F7F;
 }
 
-pre .xml .css,
+pre .coffeescript .javascript,
+pre .javascript .xml,
+pre .tex .formula,
 pre .xml .javascript,
 pre .xml .vbscript,
-pre .tex .formula {
+pre .xml .css,
+pre .xml .cdata {
   opacity: 0.5;
-}
-
+}

+ 7 - 7
package.json

@@ -21,19 +21,19 @@
     "node": "~0.8.0"
   },
   "dependencies": {
-    "underscore": "~1.3.3",
+    "underscore": "~1.5.1",
     "express": "~2.5.9",
-    "mustache": "~0.4.0",
+    "mustache": "~0.7.2",
     "socket.io": "~0.9.13"
   },
   "devDependencies": {
     "grunt-contrib-qunit": "~0.2.2",
-    "grunt-contrib-jshint": "~0.2.0",
+    "grunt-contrib-jshint": "~0.6.4",
     "grunt-contrib-cssmin": "~0.4.1",
-    "grunt-contrib-uglify": "~0.1.1",
-    "grunt-contrib-watch": "~0.2.0",
-    "grunt-contrib-sass": "~0.2.2",
-    "grunt-contrib-connect": "~0.2.0",
+    "grunt-contrib-uglify": "~0.2.4",
+    "grunt-contrib-watch": "~0.5.3",
+    "grunt-contrib-sass": "~0.5.0",
+    "grunt-contrib-connect": "~0.4.1",
     "grunt-zip": "~0.7.0",
     "grunt": "~0.4.0"
   },

+ 96 - 47
plugin/markdown/markdown.js

@@ -3,7 +3,16 @@
  * markdown inside of presentations as well as loading
  * of external markdown documents.
  */
-(function(){
+(function( root, factory ) {
+	if( typeof exports === 'object' ) {
+		module.exports = factory( require( './marked' ) );
+	}
+	else {
+		// Browser globals (root is window)
+		root.RevealMarkdown = factory( root.marked );
+		root.RevealMarkdown.initialize();
+	}
+}( this, function( marked ) {
 
 	if( typeof marked === 'undefined' ) {
 		throw 'The reveal.js Markdown plugin requires marked to be loaded';
@@ -17,6 +26,10 @@
 		});
 	}
 
+	var DEFAULT_SLIDE_SEPARATOR = '^\n---\n$',
+		DEFAULT_NOTES_SEPARATOR = 'note:';
+
+
 	/**
 	 * Retrieves the markdown contents of a slide section
 	 * element. Normalizes leading tabs/whitespace.
@@ -72,15 +85,32 @@
 
 	}
 
+	/**
+	 * Inspects the given options and fills out default
+	 * values for what's not defined.
+	 */
+	function getSlidifyOptions( options ) {
+
+		options = options || {};
+		options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
+		options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
+		options.attributes = options.attributes || '';
+
+		return options;
+
+	}
+
 	/**
 	 * Helper function for constructing a markdown slide.
 	 */
-	function createMarkdownSlide( data ) {
+	function createMarkdownSlide( content, options ) {
+
+		options = getSlidifyOptions( options );
 
-		var content = data.content || data;
+		var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
 
-		if( data.notes ) {
-			content += '<aside class="notes" data-markdown>' + data.notes + '</aside>';
+		if( notesMatch.length === 2 ) {
+			content = notesMatch[0] + '<aside class="notes" data-markdown>' + notesMatch[1].trim() + '</aside>';
 		}
 
 		return '<script type="text/template">' + content + '</script>';
@@ -91,25 +121,18 @@
 	 * Parses a data string into multiple slides based
 	 * on the passed in separator arguments.
 	 */
-	function slidifyMarkdown( markdown, options ) {
+	function slidify( markdown, options ) {
 
-		options = options || {};
-		options.separator = options.separator || '^\n---\n$';
-		options.notesSeparator = options.notesSeparator || 'note:';
-		options.attributes = options.attributes || '';
+		options = getSlidifyOptions( options );
 
 		var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
-			horizontalSeparatorRegex = new RegExp( options.separator ),
-			notesSeparatorRegex = new RegExp( options.notesSeparator, 'mgi' );
+			horizontalSeparatorRegex = new RegExp( options.separator );
 
 		var matches,
-			noteMatch,
 			lastIndex = 0,
 			isHorizontal,
 			wasHorizontal = true,
 			content,
-			notes,
-			slide,
 			sectionStack = [];
 
 		// iterate until all blocks between separators are stacked up
@@ -126,25 +149,14 @@
 
 			// pluck slide content from markdown input
 			content = markdown.substring( lastIndex, matches.index );
-			noteMatch = content.split( notesSeparatorRegex );
-
-			if( noteMatch.length === 2 ) {
-				content = noteMatch[0];
-				notes = noteMatch[1].trim();
-			}
-
-			slide = {
-				content: content,
-				notes: notes || ''
-			};
 
 			if( isHorizontal && wasHorizontal ) {
 				// add to horizontal stack
-				sectionStack.push( slide );
+				sectionStack.push( content );
 			}
 			else {
 				// add to vertical stack
-				sectionStack[sectionStack.length-1].push( slide );
+				sectionStack[sectionStack.length-1].push( content );
 			}
 
 			lastIndex = separatorRegex.lastIndex;
@@ -160,12 +172,16 @@
 		for( var i = 0, len = sectionStack.length; i < len; i++ ) {
 			// vertical
 			if( sectionStack[i].propertyIsEnumerable( length ) && typeof sectionStack[i].splice === 'function' ) {
-				markdownSections += '<section '+ options.attributes +'>' +
-										'<section data-markdown>' +  sectionStack[i].map( createMarkdownSlide ).join( '</section><section data-markdown>' ) + '</section>' +
-									'</section>';
+				markdownSections += '<section '+ options.attributes +'>';
+
+				sectionStack[i].forEach( function( child ) {
+					markdownSections += '<section data-markdown>' +  createMarkdownSlide( child, options ) + '</section>';
+				} );
+
+				markdownSections += '</section>';
 			}
 			else {
-				markdownSections += '<section '+ options.attributes +' data-markdown>' + createMarkdownSlide( sectionStack[i] ) + '</section>';
+				markdownSections += '<section '+ options.attributes +' data-markdown>' + createMarkdownSlide( sectionStack[i], options ) + '</section>';
 			}
 		}
 
@@ -173,7 +189,12 @@
 
 	}
 
-	function loadExternalMarkdown() {
+	/**
+	 * Parses any current data-markdown slides, splits
+	 * multi-slide markdown into separate sections and
+	 * handles loading of external markdown.
+	 */
+	function processSlides() {
 
 		var sections = document.querySelectorAll( '[data-markdown]'),
 			section;
@@ -198,7 +219,7 @@
 					if( xhr.readyState === 4 ) {
 						if ( xhr.status >= 200 && xhr.status < 300 ) {
 
-							section.outerHTML = slidifyMarkdown( xhr.responseText, {
+							section.outerHTML = slidify( xhr.responseText, {
 								separator: section.getAttribute( 'data-separator' ),
 								verticalSeparator: section.getAttribute( 'data-vertical' ),
 								notesSeparator: section.getAttribute( 'data-notes' ),
@@ -228,9 +249,9 @@
 				}
 
 			}
-			else if( section.getAttribute( 'data-separator' ) ) {
+			else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-vertical' ) || section.getAttribute( 'data-notes' ) ) {
 
-				section.outerHTML = slidifyMarkdown( getMarkdownFromSlide( section ), {
+				section.outerHTML = slidify( getMarkdownFromSlide( section ), {
 					separator: section.getAttribute( 'data-separator' ),
 					verticalSeparator: section.getAttribute( 'data-vertical' ),
 					notesSeparator: section.getAttribute( 'data-notes' ),
@@ -238,11 +259,20 @@
 				});
 
 			}
+			else {
+
+				section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
+
+			}
 		}
 
 	}
 
-	function convertMarkdownToHTML() {
+	/**
+	 * Converts any current data-markdown slides in the
+	 * DOM to HTML.
+	 */
+	function convertSlides() {
 
 		var sections = document.querySelectorAll( '[data-markdown]');
 
@@ -250,22 +280,41 @@
 
 			var section = sections[i];
 
-			var notes = section.querySelector( 'aside.notes' );
-			var markdown = getMarkdownFromSlide( section );
+			// Only parse the same slide once
+			if( !section.getAttribute( 'data-markdown-parsed' ) ) {
+
+				section.setAttribute( 'data-markdown-parsed', true )
 
-			section.innerHTML = marked( markdown );
+				var notes = section.querySelector( 'aside.notes' );
+				var markdown = getMarkdownFromSlide( section );
+
+				section.innerHTML = marked( markdown );
+
+				// If there were notes, we need to re-add them after
+				// having overwritten the section's HTML
+				if( notes ) {
+					section.appendChild( notes );
+				}
 
-			// If there were notes, we need to re-add them after
-			// having overwritten the section's HTML
-			if( notes ) {
-				section.appendChild( notes );
 			}
 
 		}
 
 	}
 
-	loadExternalMarkdown();
-	convertMarkdownToHTML();
+	// API
+	return {
+
+		initialize: function() {
+			processSlides();
+			convertSlides();
+		},
+
+		// TODO: Do these belong in the API?
+		processSlides: processSlides,
+		convertSlides: convertSlides,
+		slidify: slidify
+
+	};
 
-})();
+}));

+ 2 - 1
plugin/multiplex/master.js

@@ -1,6 +1,7 @@
 (function() {
-	// don't emit events from inside the previews themselves
+	// Don't emit events from inside of notes windows
 	if ( window.location.search.match( /receiver/gi ) ) { return; }
+
 	var multiplex = Reveal.getConfig().multiplex;
 
 	var socket = io.connect(multiplex.url);

+ 6 - 2
plugin/notes/notes.html

@@ -139,11 +139,11 @@
 	<body>
 
 		<div id="wrap-current-slide" class="slides">
-			<script>document.write( '<iframe width="1280" height="1024" id="current-slide" src="'+ window.opener.location.href +'"></iframe>' );</script>
+			<script>document.write( '<iframe width="1280" height="1024" id="current-slide" src="'+ window.opener.location.href +'?receiver"></iframe>' );</script>
 		</div>
 
 		<div id="wrap-next-slide" class="slides">
-			<script>document.write( '<iframe width="640" height="512" id="next-slide" src="'+ window.opener.location.href +'"></iframe>' );</script>
+			<script>document.write( '<iframe width="640" height="512" id="next-slide" src="'+ window.opener.location.href +'?receiver"></iframe>' );</script>
 			<span>UPCOMING:</span>
 		</div>
 
@@ -239,6 +239,10 @@
 					currentSlide.contentWindow.Reveal.addEventListener( 'fragmentshown', synchronizeMainWindow );
 					currentSlide.contentWindow.Reveal.addEventListener( 'fragmenthidden', synchronizeMainWindow );
 
+					// Reconfigure the notes window to remove needless UI
+					currentSlide.contentWindow.Reveal.configure({ controls: false, progress: false, overview: false });
+					nextSlide.contentWindow.Reveal.configure({ controls: false, progress: false, overview: false });
+
 				}
 				else {
 

+ 3 - 3
plugin/remotes/remotes.js

@@ -17,11 +17,11 @@
      * Detects if notes are enable and the current page is opened inside an /iframe
      * this prevents loading Remotes.io several times
      */
-    var remotesAndIsNotes = (function(){
-      return !(window.RevealNotes && self == top);
+    var isNotesAndIframe = (function(){
+        return window.RevealNotes && !(self == top);
     })();
 
-    if(!hasTouch && !remotesAndIsNotes){
+    if(!hasTouch && !isNotesAndIframe){
         head.ready( 'remotes.ne.min.js', function() {
             new Remotes("preview")
                 .on("swipe-left", function(e){ Reveal.right(); })

+ 52 - 0
test/test-markdown.html

@@ -0,0 +1,52 @@
+<!doctype html>
+<html lang="en">
+
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Test Markdown</title>
+
+		<link rel="stylesheet" href="../css/reveal.min.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="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section> -->
+
+				<!-- Slides are separated by newline + three dashes + newline, vertical slides identical but two dashes -->
+				<section data-markdown data-separator="^\n---\n$" data-vertical="^\n--\n$">
+					<script type="text/template">
+						## Slide 1.1
+
+						--
+
+						## Slide 1.2
+
+						---
+
+						## Slide 2
+					</script>
+				</section>
+
+			</div>
+
+		</div>
+
+		<script src="../lib/js/head.min.js"></script>
+		<script src="../js/reveal.min.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.js"></script>
+
+	</body>
+</html>

+ 15 - 0
test/test-markdown.js

@@ -0,0 +1,15 @@
+
+
+Reveal.addEventListener( 'ready', function() {
+
+	QUnit.module( 'Markdown' );
+
+	test( 'Vertical separator', function() {
+		strictEqual( document.querySelectorAll( '.reveal .slides>section>section' ).length, 2, 'found two slides' );
+	});
+
+
+} );
+
+Reveal.initialize();
+

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio