diff --git a/demo.md b/demo.md new file mode 100644 index 0000000000000000000000000000000000000000..1efe5f94d82609343d7e83380503967d934f091e --- /dev/null +++ b/demo.md @@ -0,0 +1,29 @@ +# External markdown + + + +## Slide 1.1 + +Content 1.1 + + +## Slide 1.2 + +Content 1.2 + + + +## Slide 2 + +Content 2.1 + + + +## Slide 3.1 + +Content 3.1 + + +## Slide 3.2 + +Content 3.2 diff --git a/index-markdown.html b/index-markdown.html new file mode 100644 index 0000000000000000000000000000000000000000..367c879803164fc77d9f66773f6f3de06d3a04f0 --- /dev/null +++ b/index-markdown.html @@ -0,0 +1,116 @@ +<!doctype html> +<html lang="en"> + + <head> + <meta charset="utf-8"> + + <title>reveal.js - The HTML Presentation Framework</title> + + <meta name="description" content="A framework for easily creating beautiful presentations using HTML"> + <meta name="author" content="Hakim El Hattab"> + + <meta name="apple-mobile-web-app-capable" content="yes" /> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> + + <link rel="stylesheet" href="css/reveal.css"> + <link rel="stylesheet" href="css/theme/default.css" id="theme"> + + <!-- For syntax highlighting --> + <link rel="stylesheet" href="lib/css/zenburn.css"> + + <!-- If the query includes 'print-pdf', use the PDF print sheet --> + <script> + document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' ); + </script> + + <!--[if lt IE 9]> + <script src="lib/js/html5shiv.js"></script> + <![endif]--> + </head> + + <body> + + <div class="reveal"> + + <!-- Any section element inside of this container is displayed as a slide --> + <div class="slides"> + + <!-- Use external markdown resource, and separate slides by three newlines; vertical slides by two newlines --> + <section data-markdown="demo.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"> + Slide 1 + --- + Slide 2 + --- + 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"> + Slide 1.1 + + -- + + Slide 1.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> + + // Full list of configuration options available here: + // https://github.com/hakimel/reveal.js#configuration + Reveal.initialize({ + controls: true, + progress: true, + history: true, + center: true, + + theme: Reveal.getQueryHash().theme, // available themes are in /css/theme + transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none + + // Optional libraries used to extend on reveal.js + dependencies: [ + { src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } }, + { src: 'plugin/markdown/showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, + { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }, + { src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } }, + { src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } } + // { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } } + ] + }); + + </script> + + </body> +</html> diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index b1660a1b39ab6a1704b70ebc855b960889114567..ae4d08b0c602f0853899917c486eb001ca14d450 100644 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -6,11 +6,7 @@ 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' ); @@ -27,11 +23,125 @@ 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 ) { section.appendChild( notes ); } - } -})(); \ No newline at end of file + }; + + querySlidingMarkdown(); + + queryMarkdownSlides(); + +})();