|
@@ -7,13 +7,11 @@
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
root.marked = require( './marked' );
|
|
|
root.RevealMarkdown = factory( root.marked );
|
|
|
- root.RevealMarkdown.initialize();
|
|
|
} else 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 ) {
|
|
|
|
|
@@ -199,81 +197,108 @@
|
|
|
*/
|
|
|
function processSlides() {
|
|
|
|
|
|
- var sections = document.querySelectorAll( '[data-markdown]'),
|
|
|
- section;
|
|
|
+ return new Promise( function( resolve ) {
|
|
|
|
|
|
- for( var i = 0, len = sections.length; i < len; i++ ) {
|
|
|
+ var externalPromises = [];
|
|
|
|
|
|
- section = sections[i];
|
|
|
+ [].slice.call( document.querySelectorAll( '[data-markdown]') ).forEach( function( section, i ) {
|
|
|
|
|
|
- if( section.getAttribute( 'data-markdown' ).length ) {
|
|
|
+ if( section.getAttribute( 'data-markdown' ).length ) {
|
|
|
|
|
|
- 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 );
|
|
|
- }
|
|
|
-
|
|
|
- xhr.onreadystatechange = function() {
|
|
|
- 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 ) {
|
|
|
+ externalPromises.push( loadExternalMarkdown( section ).then(
|
|
|
|
|
|
+ // 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 )
|
|
|
});
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
+ // 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>';
|
|
|
-
|
|
|
}
|
|
|
- }
|
|
|
- };
|
|
|
|
|
|
- xhr.open( 'GET', url, false );
|
|
|
+ ) );
|
|
|
+
|
|
|
+ }
|
|
|
+ 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 )
|
|
|
+ });
|
|
|
|
|
|
- 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 );
|
|
|
+ else {
|
|
|
+ section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
|
|
|
}
|
|
|
|
|
|
+ });
|
|
|
+
|
|
|
+ Promise.all( externalPromises ).then( resolve );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function loadExternalMarkdown( section ) {
|
|
|
+
|
|
|
+ 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 );
|
|
|
}
|
|
|
- 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 )
|
|
|
- });
|
|
|
+ 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 ) {
|
|
|
+
|
|
|
+ resolve( xhr, url );
|
|
|
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ reject( xhr, url );
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }.bind( this, section, xhr );
|
|
|
+
|
|
|
+ xhr.open( 'GET', url, true );
|
|
|
+
|
|
|
+ try {
|
|
|
+ xhr.send();
|
|
|
}
|
|
|
- else {
|
|
|
- section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
|
|
|
+ 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 );
|
|
|
}
|
|
|
- }
|
|
|
+
|
|
|
+ } );
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Check if a node value has the attributes pattern.
|
|
|
* If yes, extract it and add that value as one or several attributes
|
|
|
- * the the terget element.
|
|
|
+ * to the target element.
|
|
|
*
|
|
|
* You need Cache Killer on Chrome to see the effect on any FOM transformation
|
|
|
* directly on refresh (F5)
|
|
@@ -342,44 +367,47 @@
|
|
|
*/
|
|
|
function convertSlides() {
|
|
|
|
|
|
- var sections = document.querySelectorAll( '[data-markdown]');
|
|
|
-
|
|
|
- for( var i = 0, len = sections.length; i < len; i++ ) {
|
|
|
+ var sections = document.querySelectorAll( '[data-markdown]:not([data-markdown-parsed])');
|
|
|
|
|
|
- var section = sections[i];
|
|
|
+ [].slice.call( sections ).forEach( function( section ) {
|
|
|
|
|
|
- // Only parse the same slide once
|
|
|
- if( !section.getAttribute( 'data-markdown-parsed' ) ) {
|
|
|
+ section.setAttribute( 'data-markdown-parsed', true )
|
|
|
|
|
|
- section.setAttribute( 'data-markdown-parsed', true )
|
|
|
+ var notes = section.querySelector( 'aside.notes' );
|
|
|
+ var markdown = getMarkdownFromSlide( section );
|
|
|
|
|
|
- var notes = section.querySelector( 'aside.notes' );
|
|
|
- var markdown = getMarkdownFromSlide( section );
|
|
|
-
|
|
|
- section.innerHTML = marked( markdown );
|
|
|
- addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
|
|
|
- section.parentNode.getAttribute( 'data-element-attributes' ) ||
|
|
|
- DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
|
|
|
- section.getAttribute( 'data-attributes' ) ||
|
|
|
- section.parentNode.getAttribute( 'data-attributes' ) ||
|
|
|
- DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
|
|
|
-
|
|
|
- // If there were notes, we need to re-add them after
|
|
|
- // having overwritten the section's HTML
|
|
|
- if( notes ) {
|
|
|
- section.appendChild( notes );
|
|
|
- }
|
|
|
+ section.innerHTML = marked( markdown );
|
|
|
+ addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
|
|
|
+ section.parentNode.getAttribute( 'data-element-attributes' ) ||
|
|
|
+ DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
|
|
|
+ section.getAttribute( 'data-attributes' ) ||
|
|
|
+ section.parentNode.getAttribute( 'data-attributes' ) ||
|
|
|
+ DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
|
|
|
|
|
|
+ // If there were notes, we need to re-add them after
|
|
|
+ // having overwritten the section's HTML
|
|
|
+ if( notes ) {
|
|
|
+ section.appendChild( notes );
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ } );
|
|
|
+
|
|
|
+ return Promise.resolve();
|
|
|
|
|
|
}
|
|
|
|
|
|
// API
|
|
|
- return {
|
|
|
+ var RevealMarkdown = {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Starts processing and converting Markdown within the
|
|
|
+ * current reveal.js deck.
|
|
|
+ *
|
|
|
+ * @param {function} callback function to invoke once
|
|
|
+ * we've finished loading and parsing Markdown
|
|
|
+ */
|
|
|
+ init: function( callback ) {
|
|
|
|
|
|
- initialize: function() {
|
|
|
if( typeof marked === 'undefined' ) {
|
|
|
throw 'The reveal.js Markdown plugin requires marked to be loaded';
|
|
|
}
|
|
@@ -392,14 +420,14 @@
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ // marked can be configured via reveal.js config options
|
|
|
var options = Reveal.getConfig().markdown;
|
|
|
-
|
|
|
- if ( options ) {
|
|
|
+ if( options ) {
|
|
|
marked.setOptions( options );
|
|
|
}
|
|
|
|
|
|
- processSlides();
|
|
|
- convertSlides();
|
|
|
+ return processSlides().then( convertSlides );
|
|
|
+
|
|
|
},
|
|
|
|
|
|
// TODO: Do these belong in the API?
|
|
@@ -409,4 +437,10 @@
|
|
|
|
|
|
};
|
|
|
|
|
|
+ // Register our plugin so that reveal.js will call our
|
|
|
+ // plugin 'init' method as part of the initialization
|
|
|
+ Reveal.registerPlugin( 'markdown', RevealMarkdown );
|
|
|
+
|
|
|
+ return RevealMarkdown;
|
|
|
+
|
|
|
}));
|