diff options
Diffstat (limited to 'plugin/markdown/markdown.js')
-rwxr-xr-x | plugin/markdown/markdown.js | 143 |
1 files changed, 96 insertions, 47 deletions
diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index 31d22f1..42c847f 100755 --- a/plugin/markdown/markdown.js +++ b/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. @@ -73,14 +86,31 @@ } /** + * 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 + + }; -})(); +})); |