diff options
Diffstat (limited to 'plugin/markdown/markdown.js')
-rwxr-xr-x | plugin/markdown/markdown.js | 180 |
1 files changed, 107 insertions, 73 deletions
diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index aa08ee5..c641d81 100755 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -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; + })); |