Browse Source

Merge remote-tracking branch 'upstream/master' into solarized

asmod3us 12 years ago
parent
commit
49ada91eb1
11 changed files with 469 additions and 117 deletions
  1. 2 0
      .travis.yml
  2. 20 22
      Gruntfile.js
  3. 19 1
      README.md
  4. 0 0
      css/reveal.min.css
  5. 143 55
      js/reveal.js
  6. 1 1
      js/reveal.min.js
  7. 32 29
      package.json
  8. 97 0
      plugin/markdown/example.html
  9. 29 0
      plugin/markdown/example.md
  10. 119 9
      plugin/markdown/markdown.js
  11. 7 0
      plugin/notes/notes.html

+ 2 - 0
.travis.yml

@@ -1,3 +1,5 @@
 language: node_js
 language: node_js
 node_js:
 node_js:
   - 0.8
   - 0.8
+before_script:
+  - npm install -g grunt-cli

+ 20 - 22
grunt.js → Gruntfile.js

@@ -3,19 +3,11 @@ module.exports = function(grunt) {
 
 
 	// Project configuration
 	// Project configuration
 	grunt.initConfig({
 	grunt.initConfig({
-		pkg: '<json:package.json>',
-
-		inputJS: 'js/reveal.js',
-		inputCSS: 'css/reveal.css',
-
-		outputJS: 'js/reveal.min.js',
-		outputCSS: 'css/reveal.min.css',
-
+		pkg: grunt.file.readJSON('package.json'),
 		meta: {
 		meta: {
-			version: '2.3',
-			banner: 
+			banner:
 				'/*!\n' +
 				'/*!\n' +
-				' * reveal.js <%= meta.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
+				' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
 				' * http://lab.hakim.se/reveal-js\n' +
 				' * http://lab.hakim.se/reveal-js\n' +
 				' * MIT licensed\n' +
 				' * MIT licensed\n' +
 				' *\n' +
 				' *\n' +
@@ -23,8 +15,8 @@ module.exports = function(grunt) {
 				' */'
 				' */'
 		},
 		},
 
 
-		lint: {
-			files: [ 'grunt.js', '<%= inputJS %>' ]
+		jshint: {
+			files: [ 'Gruntfile.js', 'js/reveal.js' ]
 		},
 		},
 
 
 		// Tests will be added soon
 		// Tests will be added soon
@@ -32,17 +24,20 @@ module.exports = function(grunt) {
 			files: [ 'test/**/*.html' ]
 			files: [ 'test/**/*.html' ]
 		},
 		},
 
 
-		min: {
-			dist: {
-				src: [ '<banner:meta.banner>', '<%= inputJS %>' ],
-				dest: '<%= outputJS %>'
+		uglify: {
+			options: {
+				banner: '<%= meta.banner %>\n'
+			},
+			build: {
+				src: 'js/reveal.js',
+				dest: 'js/reveal.min.js'
 			}
 			}
 		},
 		},
 
 
-		mincss: {
+		cssmin: {
 			compress: {
 			compress: {
 				files: {
 				files: {
-					'<%= outputCSS %>': [ '<%= inputCSS %>' ]
+					'css/reveal.min.css': [ 'css/reveal.css' ]
 				}
 				}
 			}
 			}
 		},
 		},
@@ -69,16 +64,19 @@ module.exports = function(grunt) {
 		},
 		},
 
 
 		watch: {
 		watch: {
-			files: [ 'grunt.js', '<%= inputJS %>', '<%= inputCSS %>' ],
+			files: [ 'Gruntfile.js', 'js/reveal.js', 'css/reveal.css' ],
 			tasks: 'default'
 			tasks: 'default'
 		}
 		}
 
 
 	});
 	});
 
 
 	// Dependencies
 	// Dependencies
-	grunt.loadNpmTasks( 'grunt-contrib-mincss' );
+	grunt.loadNpmTasks( 'grunt-contrib-jshint' );
+	grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
+	grunt.loadNpmTasks( 'grunt-contrib-uglify' );
+	grunt.loadNpmTasks( 'grunt-contrib-watch' );
 
 
 	// Default task
 	// Default task
-	grunt.registerTask( 'default', [ 'lint', 'mincss', 'min' ] );
+	grunt.registerTask( 'default', [ 'jshint', 'cssmin', 'uglify' ] );
 
 
 };
 };

+ 19 - 1
README.md

@@ -37,7 +37,7 @@ Markup heirarchy needs to be ``<div class="reveal"> <div class="slides"> <sectio
 
 
 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 ```<script type="text/template">``` like the example below.
 
 
-This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) which in turn uses [showdown](https://github.com/coreyti/showdown/). This is 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) which in turn uses [showdown](https://github.com/coreyti/showdown/). Sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks).
 
 
 ```html
 ```html
 <section data-markdown>
 <section data-markdown>
@@ -49,6 +49,14 @@ This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Iri
 </section>
 </section>
 ```
 ```
 
 
+#### External Markdown
+
+You can write your content as a separate file and have reveal.js load it at runtime. Note the separator arguments which determine how slides are delimited in the external file.
+
+```html
+<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section>
+```
+
 ### Configuration
 ### Configuration
 
 
 At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below.
 At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below.
@@ -270,6 +278,16 @@ Multiple fragments can be applied to the same element sequentially by wrapping i
 </section>
 </section>
 ```
 ```
 
 
+The display order of fragments can be controlled using the ```data-fragment-index``` attribute.
+
+```html
+<section>
+	<p class="fragment" data-fragment-index="3">Appears last</p>
+	<p class="fragment" data-fragment-index="1">Appears first</p>
+	<p class="fragment" data-fragment-index="2">Appears second</p>
+</section>
+```
+
 ### Fragment events
 ### Fragment events
 
 
 When a slide fragment is either shown or hidden reveal.js will dispatch an event.
 When a slide fragment is either shown or hidden reveal.js will dispatch an event.

File diff suppressed because it is too large
+ 0 - 0
css/reveal.min.css


+ 143 - 55
js/reveal.js

@@ -129,6 +129,9 @@ var Reveal = (function(){
 		// A delay used to deactivate the overview mode
 		// A delay used to deactivate the overview mode
 		deactivateOverviewTimeout = 0,
 		deactivateOverviewTimeout = 0,
 
 
+		// Flags if the interaction event listeners are bound
+		eventsAreBound = false,
+
 		// Holds information about the currently ongoing touch input
 		// Holds information about the currently ongoing touch input
 		touch = {
 		touch = {
 			startX: 0,
 			startX: 0,
@@ -310,10 +313,6 @@ var Reveal = (function(){
 		// Updates the presentation to match the current configuration values
 		// Updates the presentation to match the current configuration values
 		configure();
 		configure();
 
 
-		// Force an initial layout, will thereafter be invoked as the window
-		// is resized
-		layout();
-
 		// Read the initial hash
 		// Read the initial hash
 		readURL();
 		readURL();
 
 
@@ -335,40 +334,51 @@ var Reveal = (function(){
 	/**
 	/**
 	 * Applies the configuration settings from the config object.
 	 * Applies the configuration settings from the config object.
 	 */
 	 */
-	function configure() {
+	function configure( options ) {
 
 
-		if( supports3DTransforms === false ) {
-			config.transition = 'linear';
-		}
+		dom.wrapper.classList.remove( config.transition );
 
 
-		if( config.controls && dom.controls ) {
-			dom.controls.style.display = 'block';
-		}
+		// New config options may be passed when this method
+		// is invoked through the API after initialization
+		if( typeof options === 'object' ) extend( config, options );
 
 
-		if( config.progress && dom.progress ) {
-			dom.progress.style.display = 'block';
-		}
+		// Force linear transition based on browser capabilities
+		if( supports3DTransforms === false ) config.transition = 'linear';
 
 
-		if( config.transition !== 'default' ) {
-			dom.wrapper.classList.add( config.transition );
-		}
+		dom.wrapper.classList.add( config.transition );
+
+		dom.controls.style.display = ( config.controls && dom.controls ) ? 'block' : 'none';
+		dom.progress.style.display = ( config.progress && dom.progress ) ? 'block' : 'none';
 
 
 		if( config.rtl ) {
 		if( config.rtl ) {
 			dom.wrapper.classList.add( 'rtl' );
 			dom.wrapper.classList.add( 'rtl' );
 		}
 		}
+		else {
+			dom.wrapper.classList.remove( 'rtl' );
+		}
 
 
 		if( config.center ) {
 		if( config.center ) {
 			dom.wrapper.classList.add( 'center' );
 			dom.wrapper.classList.add( 'center' );
 		}
 		}
+		else {
+			dom.wrapper.classList.remove( 'center' );
+		}
 
 
 		if( config.mouseWheel ) {
 		if( config.mouseWheel ) {
 			document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
 			document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
 			document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
 			document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
 		}
 		}
+		else {
+			document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
+			document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false );
+		}
 
 
 		// 3D links
 		// 3D links
 		if( config.rollingLinks ) {
 		if( config.rollingLinks ) {
-			linkify();
+			enable3DLinks();
+		}
+		else {
+			disable3DLinks();
 		}
 		}
 
 
 		// Load the theme in the config, if it's not already loaded
 		// Load the theme in the config, if it's not already loaded
@@ -383,6 +393,9 @@ var Reveal = (function(){
 			}
 			}
 		}
 		}
 
 
+		// Force a layout to make sure the current config is accounted for
+		layout();
+
 	}
 	}
 
 
 	/**
 	/**
@@ -390,6 +403,8 @@ var Reveal = (function(){
 	 */
 	 */
 	function addEventListeners() {
 	function addEventListeners() {
 
 
+		eventsAreBound = true;
+
 		window.addEventListener( 'hashchange', onWindowHashChange, false );
 		window.addEventListener( 'hashchange', onWindowHashChange, false );
 		window.addEventListener( 'resize', onWindowResize, false );
 		window.addEventListener( 'resize', onWindowResize, false );
 
 
@@ -424,6 +439,8 @@ var Reveal = (function(){
 	 */
 	 */
 	function removeEventListeners() {
 	function removeEventListeners() {
 
 
+		eventsAreBound = false;
+
 		document.removeEventListener( 'keydown', onDocumentKeyDown, false );
 		document.removeEventListener( 'keydown', onDocumentKeyDown, false );
 		window.removeEventListener( 'hashchange', onWindowHashChange, false );
 		window.removeEventListener( 'hashchange', onWindowHashChange, false );
 		window.removeEventListener( 'resize', onWindowResize, false );
 		window.removeEventListener( 'resize', onWindowResize, false );
@@ -524,28 +541,79 @@ var Reveal = (function(){
 	/**
 	/**
 	 * Wrap all links in 3D goodness.
 	 * Wrap all links in 3D goodness.
 	 */
 	 */
-	function linkify() {
+	function enable3DLinks() {
 
 
 		if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) {
 		if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) {
-			var nodes = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
+			var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
 
 
-			for( var i = 0, len = nodes.length; i < len; i++ ) {
-				var node = nodes[i];
+			for( var i = 0, len = anchors.length; i < len; i++ ) {
+				var anchor = anchors[i];
 
 
-				if( node.textContent && !node.querySelector( '*' ) && ( !node.className || !node.classList.contains( node, 'roll' ) ) ) {
+				if( anchor.textContent && !anchor.querySelector( '*' ) && ( !anchor.className || !anchor.classList.contains( anchor, 'roll' ) ) ) {
 					var span = document.createElement('span');
 					var span = document.createElement('span');
-					span.setAttribute('data-title', node.text);
-					span.innerHTML = node.innerHTML;
+					span.setAttribute('data-title', anchor.text);
+					span.innerHTML = anchor.innerHTML;
 
 
-					node.classList.add( 'roll' );
-					node.innerHTML = '';
-					node.appendChild(span);
+					anchor.classList.add( 'roll' );
+					anchor.innerHTML = '';
+					anchor.appendChild(span);
 				}
 				}
 			}
 			}
 		}
 		}
 
 
 	}
 	}
 
 
+	/**
+	 * Unwrap all 3D links.
+	 */
+	function disable3DLinks() {
+
+		var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a.roll' );
+
+		for( var i = 0, len = anchors.length; i < len; i++ ) {
+			var anchor = anchors[i];
+			var span = anchor.querySelector( 'span' );
+
+			if( span ) {
+				anchor.classList.remove( 'roll' );
+				anchor.innerHTML = span.innerHTML;
+			}
+		}
+
+	}
+
+	/**
+	 * Return a sorted fragments list, ordered by an increasing
+	 * "data-fragment-index" attribute.
+	 *
+	 * Fragments will be revealed in the order that they are returned by
+	 * this function, so you can use the index attributes to control the 
+	 * order of fragment appearance.
+	 *
+	 * To maintain a sensible default fragment order, fragments are presumed
+	 * to be passed in document order. This function adds a "fragment-index"
+	 * attribute to each node if such an attribute is not already present,
+	 * and sets that attribute to an integer value which is the position of
+	 * the fragment within the fragments list.
+	 */
+	function sortFragments( fragments ) {
+
+		var a = toArray( fragments );
+
+		a.forEach( function( el, idx ) {
+			if( !el.hasAttribute( 'data-fragment-index' ) ) {
+				el.setAttribute( 'data-fragment-index', idx );
+			}
+		} );
+
+		a.sort( function( l, r ) {
+			return l.getAttribute( 'data-fragment-index' ) - r.getAttribute( 'data-fragment-index');
+		} );
+
+		return a
+
+	}
+
 	/**
 	/**
 	 * Applies JavaScript-controlled layout rules to the
 	 * Applies JavaScript-controlled layout rules to the
 	 * presentation.
 	 * presentation.
@@ -602,31 +670,30 @@ var Reveal = (function(){
 				dom.slides.style.transform = transform;
 				dom.slides.style.transform = transform;
 			}
 			}
 
 
-			if( config.center ) {
-
-				// Select all slides, vertical and horizontal
-				var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
-
-				// Determine the minimum top offset for slides
-				var minTop = -slideHeight / 2;
+			// Select all slides, vertical and horizontal
+			var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
 
 
-				for( var i = 0, len = slides.length; i < len; i++ ) {
-					var slide = slides[ i ];
+			for( var i = 0, len = slides.length; i < len; i++ ) {
+				var slide = slides[ i ];
 
 
-					// Don't bother updating invisible slides
-					if( slide.style.display === 'none' ) {
-						continue;
-					}
+				// Don't bother updating invisible slides
+				if( slide.style.display === 'none' ) {
+					continue;
+				}
 
 
+				if( config.center ) {
 					// Vertical stacks are not centered since their section
 					// Vertical stacks are not centered since their section
 					// children will be
 					// children will be
 					if( slide.classList.contains( 'stack' ) ) {
 					if( slide.classList.contains( 'stack' ) ) {
 						slide.style.top = 0;
 						slide.style.top = 0;
 					}
 					}
 					else {
 					else {
-						slide.style.top = Math.max( - ( slide.offsetHeight / 2 ) - 20, minTop ) + 'px';
+						slide.style.top = Math.max( - ( slide.offsetHeight / 2 ) - 20, -slideHeight / 2 ) + 'px';
 					}
 					}
 				}
 				}
+				else {
+					slide.style.top = '';
+				}
 
 
 			}
 			}
 
 
@@ -871,9 +938,15 @@ var Reveal = (function(){
 	 */
 	 */
 	function pause() {
 	function pause() {
 
 
+		var wasPaused = dom.wrapper.classList.contains( 'paused' );
+
 		cancelAutoSlide();
 		cancelAutoSlide();
 		dom.wrapper.classList.add( 'paused' );
 		dom.wrapper.classList.add( 'paused' );
 
 
+		if( wasPaused === false ) {
+			dispatchEvent( 'paused' );
+		}
+
 	}
 	}
 
 
 	/**
 	/**
@@ -881,9 +954,15 @@ var Reveal = (function(){
 	 */
 	 */
 	function resume() {
 	function resume() {
 
 
+		var wasPaused = dom.wrapper.classList.contains( 'paused' );
+
 		cueAutoSlide();
 		cueAutoSlide();
 		dom.wrapper.classList.remove( 'paused' );
 		dom.wrapper.classList.remove( 'paused' );
 
 
+		if( wasPaused ) {
+			dispatchEvent( 'resumed' );
+		}
+
 	}
 	}
 
 
 	/**
 	/**
@@ -996,7 +1075,7 @@ var Reveal = (function(){
 
 
 		// Show fragment, if specified
 		// Show fragment, if specified
 		if( typeof f !== 'undefined' ) {
 		if( typeof f !== 'undefined' ) {
-			var fragments = currentSlide.querySelectorAll( '.fragment' );
+			var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
 
 
 			toArray( fragments ).forEach( function( fragment, indexf ) {
 			toArray( fragments ).forEach( function( fragment, indexf ) {
 				if( indexf < f ) {
 				if( indexf < f ) {
@@ -1367,7 +1446,8 @@ var Reveal = (function(){
 
 
 		// Vertical slides:
 		// Vertical slides:
 		if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
 		if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
-			var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
+			var verticalFragments = sortFragments( document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ) );
+
 			if( verticalFragments.length ) {
 			if( verticalFragments.length ) {
 				verticalFragments[0].classList.add( 'visible' );
 				verticalFragments[0].classList.add( 'visible' );
 
 
@@ -1378,7 +1458,8 @@ var Reveal = (function(){
 		}
 		}
 		// Horizontal slides:
 		// Horizontal slides:
 		else {
 		else {
-			var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' );
+			var horizontalFragments = sortFragments( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ) );
+
 			if( horizontalFragments.length ) {
 			if( horizontalFragments.length ) {
 				horizontalFragments[0].classList.add( 'visible' );
 				horizontalFragments[0].classList.add( 'visible' );
 
 
@@ -1402,7 +1483,8 @@ var Reveal = (function(){
 
 
 		// Vertical slides:
 		// Vertical slides:
 		if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
 		if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
-			var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' );
+			var verticalFragments = sortFragments( document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' ) );
+
 			if( verticalFragments.length ) {
 			if( verticalFragments.length ) {
 				verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
 				verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
 
 
@@ -1413,7 +1495,8 @@ var Reveal = (function(){
 		}
 		}
 		// Horizontal slides:
 		// Horizontal slides:
 		else {
 		else {
-			var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' );
+			var horizontalFragments = sortFragments( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' ) );
+
 			if( horizontalFragments.length ) {
 			if( horizontalFragments.length ) {
 				horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
 				horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
 
 
@@ -1783,22 +1866,26 @@ var Reveal = (function(){
 
 
 		// TODO There's a bug here where the event listeners are not
 		// TODO There's a bug here where the event listeners are not
 		// removed after deactivating the overview.
 		// removed after deactivating the overview.
-		if( isOverview() ) {
+		if( eventsAreBound && isOverview() ) {
 			event.preventDefault();
 			event.preventDefault();
 
 
-			deactivateOverview();
-
 			var element = event.target;
 			var element = event.target;
 
 
 			while( element && !element.nodeName.match( /section/gi ) ) {
 			while( element && !element.nodeName.match( /section/gi ) ) {
 				element = element.parentNode;
 				element = element.parentNode;
 			}
 			}
 
 
-			if( element.nodeName.match( /section/gi ) ) {
-				var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
-					v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
+			if( element && !element.classList.contains( 'disabled' ) ) {
+
+				deactivateOverview();
+
+				if( element.nodeName.match( /section/gi ) ) {
+					var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
+						v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
+
+					slide( h, v );
+				}
 
 
-				slide( h, v );
 			}
 			}
 		}
 		}
 
 
@@ -1812,6 +1899,7 @@ var Reveal = (function(){
 
 
 	return {
 	return {
 		initialize: initialize,
 		initialize: initialize,
+		configure: configure,
 
 
 		// Navigation methods
 		// Navigation methods
 		slide: slide,
 		slide: slide,
@@ -1919,4 +2007,4 @@ var Reveal = (function(){
 		}
 		}
 	};
 	};
 
 
-})();
+})();

File diff suppressed because it is too large
+ 1 - 1
js/reveal.min.js


+ 32 - 29
package.json

@@ -1,31 +1,34 @@
 {
 {
-	"name": "reveal.js",
-	"version": "2.3.0",
-	"description": "The HTML Presentation Framework",
-	"homepage": "http://lab.hakim.se/reveal-js",
-	"author": {
-		"name": "Hakim El Hattab",
-		"email": "hakim.elhattab@gmail.com",
-		"web": "http://hakim.se"
-	},
-	"repository": {
-		"type": "git",
-		"url": "git://github.com/hakimel/reveal.js.git"
-	},
-	"engines": {
-		"node": "~0.8.0"
-	},
-	"scripts": {
-		"test": "grunt lint qunit"
-	},
-	"dependencies": {
-		"underscore" : "~1.3.3",
-		"express" : "~2.5.9",
-		"socket.io" : "~0.9.6",
-		"mustache" : "~0.4.0"
-	},
-	"devDependencies": {
-		"grunt-contrib-mincss": "~0.3.1",
-		"grunt": "~0.3.17"
-	}
+  "name": "reveal.js",
+  "version": "2.3.0",
+  "description": "The HTML Presentation Framework",
+  "homepage": "http://lab.hakim.se/reveal-js",
+  "author": {
+    "name": "Hakim El Hattab",
+    "email": "hakim.elhattab@gmail.com",
+    "web": "http://hakim.se"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/hakimel/reveal.js.git"
+  },
+  "engines": {
+    "node": "~0.8.0"
+  },
+  "scripts": {
+    "test": "grunt jshint"
+  },
+  "dependencies": {
+    "underscore": "~1.3.3",
+    "express": "~2.5.9",
+    "socket.io": "~0.9.6",
+    "mustache": "~0.4.0"
+  },
+  "devDependencies": {
+    "grunt-contrib-jshint": "~0.2.0",
+    "grunt-contrib-cssmin": "~0.4.1",
+    "grunt-contrib-uglify": "~0.1.1",
+    "grunt-contrib-watch": "~0.2.0",
+    "grunt": "~0.4.0"
+  }
 }
 }

+ 97 - 0
plugin/markdown/example.html

@@ -0,0 +1,97 @@
+<!doctype html>
+<html lang="en">
+
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Markdown Demo</title>
+
+		<link rel="stylesheet" href="../../css/reveal.css">
+		<link rel="stylesheet" href="../../css/theme/default.css" id="theme">
+	</head>
+
+	<body>
+
+		<div class="reveal">
+
+			<div class="slides">
+
+                <!-- Use external markdown resource, and separate slides by three newlines; vertical slides by two newlines -->
+                <section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section>
+
+                <!-- Slides are separated by three dashes (quick 'n dirty regular expression) -->
+                <section data-markdown data-separator="---">
+                    <script type="text/template">
+                        ## Demo 1
+                        Slide 1
+                        ---
+                        ## Demo 1
+                        Slide 2
+                        ---
+                        ## Demo 1
+                        Slide 3
+                    </script>
+                </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">
+                        ## Demo 2
+                        Slide 1.1
+
+                        --
+
+                        ## Demo 2
+                        Slide 1.2
+
+                        ---
+
+                        ## Demo 2
+                        Slide 2
+                    </script>
+                </section>
+
+                <!-- No "extra" slides, since there are no separators defined (so they'll become horizontal rulers) -->
+                <section data-markdown>
+                    <script type="text/template">
+                        A
+
+                        ---
+
+                        B
+
+                        ---
+
+                        C
+                    </script>
+                </section>
+
+            </div>
+		</div>
+
+		<script src="../../lib/js/head.min.js"></script>
+		<script src="../../js/reveal.js"></script>
+
+		<script>
+
+			Reveal.initialize({
+				controls: true,
+				progress: true,
+				history: true,
+				center: true,
+
+				theme: Reveal.getQueryHash().theme,
+				transition: Reveal.getQueryHash().transition || 'default',
+
+				// Optional libraries used to extend on reveal.js
+				dependencies: [
+					{ src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } },
+					{ src: 'showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
+					{ src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }
+				]
+			});
+
+		</script>
+
+	</body>
+</html>

+ 29 - 0
plugin/markdown/example.md

@@ -0,0 +1,29 @@
+# Markdown Demo
+
+
+
+## External 1.1
+
+Content 1.1
+
+
+## External 1.2
+
+Content 1.2
+
+
+
+## External 2
+
+Content 2.1
+
+
+
+## External 3.1
+
+Content 3.1
+
+
+## External 3.2
+
+Content 3.2

+ 119 - 9
plugin/markdown/markdown.js

@@ -6,16 +6,12 @@
         throw 'The reveal.js Markdown plugin requires Showdown to be loaded';
         throw 'The reveal.js Markdown plugin requires Showdown to be loaded';
     }
     }
 
 
-    var sections = document.querySelectorAll( '[data-markdown]' );
-
-    for( var i = 0, len = sections.length; i < len; i++ ) {
-        var section = sections[i];
-        var notes = section.querySelector( 'aside.notes' );
+    var stripLeadingWhitespace = function(section) {
 
 
         var template = section.querySelector( 'script' );
         var 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 ).innerHTML;
+        var text = ( template || section ).textContent;
 
 
         var leadingWs = text.match(/^\n?(\s*)/)[1].length,
         var leadingWs = text.match(/^\n?(\s*)/)[1].length,
             leadingTabs = text.match(/^\n?(\t*)/)[1].length;
             leadingTabs = text.match(/^\n?(\t*)/)[1].length;
@@ -27,11 +23,125 @@
             text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
             text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
         }
         }
 
 
-        section.innerHTML = (new Showdown.converter()).makeHtml(text);
+        return text;
+
+    };
+
+    var slidifyMarkdown = function(markdown, separator, vertical) {
+
+        separator = separator || '^\n---\n$';
+
+        var reSeparator = new RegExp(separator + (vertical ? '|' + vertical : ''), 'mg'),
+            reHorSeparator = new RegExp(separator),
+            matches,
+            lastIndex = 0,
+            isHorizontal,
+            wasHorizontal = true,
+            content,
+            sectionStack = [],
+            markdownSections = '';
+
+        // iterate until all blocks between separators are stacked up
+        while( matches = reSeparator.exec(markdown) ) {
+
+            // determine direction (horizontal by default)
+            isHorizontal = reHorSeparator.test(matches[0]);
+
+            if( !isHorizontal && wasHorizontal ) {
+                // create vertical stack
+                sectionStack.push([]);
+            }
+
+            // pluck slide content from markdown input
+            content = markdown.substring(lastIndex, matches.index);
+
+            if( isHorizontal && wasHorizontal ) {
+                // add to horizontal stack
+                sectionStack.push(content);
+            } else {
+                // add to vertical stack
+                sectionStack[sectionStack.length-1].push(content);
+            }
+
+            lastIndex = reSeparator.lastIndex;
+            wasHorizontal = isHorizontal;
+
+        }
+
+        // add the remaining slide
+        (wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1]).push(markdown.substring(lastIndex));
+
+        // flatten the hierarchical stack, and insert <section data-markdown> tags
+        for( var k = 0, klen = sectionStack.length; k < klen; k++ ) {
+            markdownSections += typeof sectionStack[k] === 'string'
+                ? '<section data-markdown>' + sectionStack[k] + '</section>'
+                : '<section><section data-markdown>' + sectionStack[k].join('</section><section data-markdown>') + '</section></section>';
+        }
+
+        return markdownSections;
+    };
+
+    var querySlidingMarkdown = function() {
+
+        var sections = document.querySelectorAll( '[data-markdown]'),
+            section;
+
+        for( var j = 0, jlen = sections.length; j < jlen; j++ ) {
+
+            section = sections[j];
+
+            if( section.getAttribute('data-markdown').length ) {
+
+                var xhr = new XMLHttpRequest(),
+                    url = section.getAttribute('data-markdown');
+
+                xhr.onreadystatechange = function () {
+                    if( xhr.readyState === 4 ) {
+                        section.outerHTML = slidifyMarkdown( xhr.responseText, section.getAttribute('data-separator'), section.getAttribute('data-vertical') );
+                    }
+                };
+
+                xhr.open('GET', url, false);
+                xhr.send();
+
+            } else if( section.getAttribute('data-separator') ) {
+
+                var markdown = stripLeadingWhitespace(section);
+                section.outerHTML = slidifyMarkdown( markdown, section.getAttribute('data-separator'), section.getAttribute('data-vertical') );
+
+            }
+        }
+
+    };
+
+    var queryMarkdownSlides = function() {
+
+        var sections = document.querySelectorAll( '[data-markdown]');
+
+        for( var j = 0, jlen = sections.length; j < jlen; j++ ) {
+
+            makeHtml(sections[j]);
+
+        }
+
+    };
+
+    var makeHtml = function(section) {
+
+        var notes = section.querySelector( 'aside.notes' );
+
+        var markdown = stripLeadingWhitespace(section);
+
+        section.innerHTML = (new Showdown.converter()).makeHtml(markdown);
 
 
         if( notes ) {
         if( notes ) {
             section.appendChild( notes );
             section.appendChild( notes );
         }
         }
-    }
 
 
-})();
+    };
+
+    querySlidingMarkdown();
+
+    queryMarkdownSlides();
+
+})();

+ 7 - 0
plugin/notes/notes.html

@@ -225,6 +225,13 @@
 
 
 					}, 1000 );
 					}, 1000 );
 
 
+					// Navigate the main window when the notes slide changes
+					currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', function( event ) {
+
+						window.opener.Reveal.slide( event.indexh, event.indexv );
+
+					} );
+
 				}
 				}
 				else {
 				else {
 
 

Some files were not shown because too many files changed in this diff