Browse Source

reveal.js plugin flow now uses promises, refactor markdown plugin to use promises

Hakim El Hattab 5 years ago
parent
commit
d780352b7f
3 changed files with 109 additions and 85 deletions
  1. 16 1
      js/reveal.js
  2. 72 73
      plugin/markdown/markdown.js
  3. 21 11
      plugin/notes/notes.js

+ 16 - 1
js/reveal.js

@@ -546,7 +546,7 @@
 			// If the plugin has an 'init' method, initialize and
 			// wait for the callback
 			if( typeof plugin.init === 'function' ) {
-				plugin.init( function() {
+				plugin.init().then( function() {
 					if( --pluginsToInitialize === 0 ) {
 						loadAsyncDependencies();
 					}
@@ -1551,11 +1551,21 @@
 
 	/**
 	 * Registers a new plugin with this reveal.js instance.
+	 *
+	 * reveal.js waits for all regisered plugins to initialize
+	 * before considering itself ready, as long as the plugin
+	 * is registered before calling `Reveal.initialize()`.
 	 */
 	function registerPlugin( id, plugin ) {
 
 		plugins[id] = plugin;
 
+		// If a plugin is registered after reveal.js is loaded,
+		// initialize it right away
+		if( loaded && typeof plugin.init === 'function' ) {
+			plugin.init();
+		}
+
 	}
 
 	/**
@@ -5841,6 +5851,11 @@
 			return dom.wrapper || document.querySelector( '.reveal' );
 		},
 
+		// Returns a hash with all registered plugins
+		getPlugins: function() {
+			return plugins;
+		},
+
 		// Returns true if we're currently on the first slide
 		isFirstSlide: function() {
 			return ( indexh === 0 && indexv === 0 );

+ 72 - 73
plugin/markdown/markdown.js

@@ -22,10 +22,6 @@
 
 	var SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__';
 
-	var markdownFilesToLoad = 0;
-
-	var loadCallback;
-
 
 	/**
 	 * Retrieves the markdown contents of a slide section
@@ -201,53 +197,41 @@
 	 */
 	function processSlides() {
 
-		[].slice.call( document.querySelectorAll( '[data-markdown]') ).forEach( function( section, i ) {
-
-			if( section.getAttribute( 'data-markdown' ).length ) {
-
-				loadExternalMarkdown( section );
-
-			}
-			else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {
-
-				section.outerHTML = slidify( getMarkdownFromSlide( section ), {
-					separator: section.getAttribute( 'data-separator' ),
-					verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
-					notesSeparator: section.getAttribute( 'data-separator-notes' ),
-					attributes: getForwardedAttributes( section )
-				});
-
-			}
-			else {
-				section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
-			}
-
-		});
+		return new Promise( function( resolve ) {
 
-		checkIfLoaded();
+			var externalPromises = [];
 
-	}
+			[].slice.call( document.querySelectorAll( '[data-markdown]') ).forEach( function( section, i ) {
 
-	function loadExternalMarkdown( section ) {
+				if( section.getAttribute( 'data-markdown' ).length ) {
 
-		markdownFilesToLoad += 1;
+					externalPromises.push( loadExternalMarkdown( section ).then(
 
-		var xhr = new XMLHttpRequest(),
-			url = section.getAttribute( 'data-markdown' );
+						// Finished loading external file
+						function( xhr, url ) {
+							section.outerHTML = slidify( xhr.responseText, {
+								separator: section.getAttribute( 'data-separator' ),
+								verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
+								notesSeparator: section.getAttribute( 'data-separator-notes' ),
+								attributes: getForwardedAttributes( section )
+							});
+						},
 
-		datacharset = section.getAttribute( 'data-charset' );
+						// Failed to load markdown
+						function( xhr, url ) {
+							section.outerHTML = '<section data-state="alert">' +
+								'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
+								'Check your browser\'s JavaScript console for more details.' +
+								'<p>Remember that you need to serve the presentation HTML from a HTTP server.</p>' +
+								'</section>';
+						}
 
-		// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
-		if( datacharset != null && datacharset != '' ) {
-			xhr.overrideMimeType( 'text/html; charset=' + datacharset );
-		}
+					) );
 
-		xhr.onreadystatechange = function( section, xhr ) {
-			if( xhr.readyState === 4 ) {
-				// file protocol yields status code 0 (useful for local debug, mobile applications etc.)
-				if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
+				}
+				else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {
 
-					section.outerHTML = slidify( xhr.responseText, {
+					section.outerHTML = slidify( getMarkdownFromSlide( section ), {
 						separator: section.getAttribute( 'data-separator' ),
 						verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
 						notesSeparator: section.getAttribute( 'data-separator-notes' ),
@@ -256,31 +240,58 @@
 
 				}
 				else {
+					section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
+				}
 
-					section.outerHTML = '<section data-state="alert">' +
-						'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
-						'Check your browser\'s JavaScript console for more details.' +
-						'<p>Remember that you need to serve the presentation HTML from a HTTP server.</p>' +
-						'</section>';
+			});
 
-				}
+			Promise.all( externalPromises ).then( resolve );
+
+		} );
 
-				convertSlides();
+	}
 
-				markdownFilesToLoad -= 1;
+	function loadExternalMarkdown( section ) {
 
-				checkIfLoaded();
+		return new Promise( function( resolve, reject ) {
+
+			var xhr = new XMLHttpRequest(),
+				url = section.getAttribute( 'data-markdown' );
+
+			datacharset = section.getAttribute( 'data-charset' );
+
+			// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
+			if( datacharset != null && datacharset != '' ) {
+				xhr.overrideMimeType( 'text/html; charset=' + datacharset );
 			}
-		}.bind( this, section, xhr );
 
-		xhr.open( 'GET', url, true );
+			xhr.onreadystatechange = function( section, xhr ) {
+				if( xhr.readyState === 4 ) {
+					// file protocol yields status code 0 (useful for local debug, mobile applications etc.)
+					if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
 
-		try {
-			xhr.send();
-		}
-		catch ( e ) {
-			alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
-		}
+						resolve( xhr, url );
+
+					}
+					else {
+
+						reject( xhr, url );
+
+					}
+				}
+			}.bind( this, section, xhr );
+
+			xhr.open( 'GET', url, true );
+
+			try {
+				xhr.send();
+			}
+			catch ( e ) {
+				alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
+				resolve( xhr, url );
+			}
+
+		} );
 
 	}
 
@@ -381,16 +392,7 @@
 
 		} );
 
-	}
-
-	function checkIfLoaded() {
-
-		if( markdownFilesToLoad === 0 ) {
-			if( loadCallback ) {
-				loadCallback();
-				loadCallback = null;
-			}
-		}
+		return Promise.resolve();
 
 	}
 
@@ -424,10 +426,7 @@
 				marked.setOptions( options );
 			}
 
-			loadCallback = callback;
-
-			processSlides();
-			convertSlides();
+			return processSlides().then( convertSlides );
 
 		},
 

+ 21 - 11
plugin/notes/notes.js

@@ -151,20 +151,30 @@ var RevealNotes = (function() {
 
 	}
 
-	if( !/receiver/i.test( window.location.search ) ) {
+	return {
+		init: function() {
 
-		// If the there's a 'notes' query set, open directly
-		if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
-			openNotes();
-		}
+			if( !/receiver/i.test( window.location.search ) ) {
+
+				// If the there's a 'notes' query set, open directly
+				if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
+					openNotes();
+				}
 
-		// Open the notes when the 's' key is hit
-		Reveal.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() {
-			openNotes();
-		} );
+				// Open the notes when the 's' key is hit
+				Reveal.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() {
+					openNotes();
+				} );
 
-	}
+			}
+
+			return Promise.resolve();
 
-	return { open: openNotes };
+		},
+
+		open: openNotes
+	};
 
 })();
+
+Reveal.registerPlugin( 'notes', RevealNotes );