1
0
Fork 0

Merge remote-tracking branch 'upstream/master' into solarized

This commit is contained in:
asmod3us 2013-02-28 17:28:07 +01:00
commit 49ada91eb1
11 changed files with 471 additions and 119 deletions

View File

@ -1,3 +1,5 @@
language: node_js language: node_js
node_js: node_js:
- 0.8 - 0.8
before_script:
- npm install -g grunt-cli

View File

@ -3,19 +3,11 @@ module.exports = function(grunt) {
// Project configuration // Project configuration
grunt.initConfig({ grunt.initConfig({
pkg: '<json:package.json>', pkg: grunt.file.readJSON('package.json'),
inputJS: 'js/reveal.js',
inputCSS: 'css/reveal.css',
outputJS: 'js/reveal.min.js',
outputCSS: 'css/reveal.min.css',
meta: { meta: {
version: '2.3',
banner: banner:
'/*!\n' + '/*!\n' +
' * reveal.js <%= meta.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' + ' * reveal.js <%= pkg.version %> (<%= grunt.template.today("yyyy-mm-dd, HH:MM") %>)\n' +
' * http://lab.hakim.se/reveal-js\n' + ' * http://lab.hakim.se/reveal-js\n' +
' * MIT licensed\n' + ' * MIT licensed\n' +
' *\n' + ' *\n' +
@ -23,8 +15,8 @@ module.exports = function(grunt) {
' */' ' */'
}, },
lint: { jshint: {
files: [ 'grunt.js', '<%= inputJS %>' ] files: [ 'Gruntfile.js', 'js/reveal.js' ]
}, },
// Tests will be added soon // Tests will be added soon
@ -32,17 +24,20 @@ module.exports = function(grunt) {
files: [ 'test/**/*.html' ] files: [ 'test/**/*.html' ]
}, },
min: { uglify: {
dist: { options: {
src: [ '<banner:meta.banner>', '<%= inputJS %>' ], banner: '<%= meta.banner %>\n'
dest: '<%= outputJS %>' },
build: {
src: 'js/reveal.js',
dest: 'js/reveal.min.js'
} }
}, },
mincss: { cssmin: {
compress: { compress: {
files: { files: {
'<%= outputCSS %>': [ '<%= inputCSS %>' ] 'css/reveal.min.css': [ 'css/reveal.css' ]
} }
} }
}, },
@ -69,16 +64,19 @@ module.exports = function(grunt) {
}, },
watch: { watch: {
files: [ 'grunt.js', '<%= inputJS %>', '<%= inputCSS %>' ], files: [ 'Gruntfile.js', 'js/reveal.js', 'css/reveal.css' ],
tasks: 'default' tasks: 'default'
} }
}); });
// Dependencies // Dependencies
grunt.loadNpmTasks( 'grunt-contrib-mincss' ); grunt.loadNpmTasks( 'grunt-contrib-jshint' );
grunt.loadNpmTasks( 'grunt-contrib-cssmin' );
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
grunt.loadNpmTasks( 'grunt-contrib-watch' );
// Default task // Default task
grunt.registerTask( 'default', [ 'lint', 'mincss', 'min' ] ); grunt.registerTask( 'default', [ 'jshint', 'cssmin', 'uglify' ] );
}; };

View File

@ -37,7 +37,7 @@ Markup heirarchy needs to be ``<div class="reveal"> <div class="slides"> <sectio
It's possible to write your slides using Markdown. To enable Markdown, add the ```data-markdown``` attribute to your ```<section>``` elements and wrap the contents in a ```<script type="text/template">``` like the example below. It's possible to write your slides using Markdown. To enable Markdown, add the ```data-markdown``` attribute to your ```<section>``` elements and wrap the contents in a ```<script type="text/template">``` like the example below.
This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) which in turn uses [showdown](https://github.com/coreyti/showdown/). This is sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks). This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Irish](https://github.com/paulirish) which in turn uses [showdown](https://github.com/coreyti/showdown/). Sensitive to indentation (avoid mixing tabs and spaces) and line breaks (avoid consecutive breaks).
```html ```html
<section data-markdown> <section data-markdown>
@ -49,6 +49,14 @@ This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Iri
</section> </section>
``` ```
#### External Markdown
You can write your content as a separate file and have reveal.js load it at runtime. Note the separator arguments which determine how slides are delimited in the external file.
```html
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n"></section>
```
### Configuration ### Configuration
At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below. At the end of your page you need to initialize reveal by running the following code. Note that all config values are optional and will default as specified below.
@ -270,6 +278,16 @@ Multiple fragments can be applied to the same element sequentially by wrapping i
</section> </section>
``` ```
The display order of fragments can be controlled using the ```data-fragment-index``` attribute.
```html
<section>
<p class="fragment" data-fragment-index="3">Appears last</p>
<p class="fragment" data-fragment-index="1">Appears first</p>
<p class="fragment" data-fragment-index="2">Appears second</p>
</section>
```
### Fragment events ### Fragment events
When a slide fragment is either shown or hidden reveal.js will dispatch an event. When a slide fragment is either shown or hidden reveal.js will dispatch an event.

2
css/reveal.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -129,6 +129,9 @@ var Reveal = (function(){
// A delay used to deactivate the overview mode // A delay used to deactivate the overview mode
deactivateOverviewTimeout = 0, deactivateOverviewTimeout = 0,
// Flags if the interaction event listeners are bound
eventsAreBound = false,
// Holds information about the currently ongoing touch input // Holds information about the currently ongoing touch input
touch = { touch = {
startX: 0, startX: 0,
@ -310,10 +313,6 @@ var Reveal = (function(){
// Updates the presentation to match the current configuration values // Updates the presentation to match the current configuration values
configure(); configure();
// Force an initial layout, will thereafter be invoked as the window
// is resized
layout();
// Read the initial hash // Read the initial hash
readURL(); readURL();
@ -335,40 +334,51 @@ var Reveal = (function(){
/** /**
* Applies the configuration settings from the config object. * Applies the configuration settings from the config object.
*/ */
function configure() { function configure( options ) {
if( supports3DTransforms === false ) { dom.wrapper.classList.remove( config.transition );
config.transition = 'linear';
}
if( config.controls && dom.controls ) { // New config options may be passed when this method
dom.controls.style.display = 'block'; // is invoked through the API after initialization
} if( typeof options === 'object' ) extend( config, options );
if( config.progress && dom.progress ) { // Force linear transition based on browser capabilities
dom.progress.style.display = 'block'; if( supports3DTransforms === false ) config.transition = 'linear';
}
if( config.transition !== 'default' ) { dom.wrapper.classList.add( config.transition );
dom.wrapper.classList.add( config.transition );
} dom.controls.style.display = ( config.controls && dom.controls ) ? 'block' : 'none';
dom.progress.style.display = ( config.progress && dom.progress ) ? 'block' : 'none';
if( config.rtl ) { if( config.rtl ) {
dom.wrapper.classList.add( 'rtl' ); dom.wrapper.classList.add( 'rtl' );
} }
else {
dom.wrapper.classList.remove( 'rtl' );
}
if( config.center ) { if( config.center ) {
dom.wrapper.classList.add( 'center' ); dom.wrapper.classList.add( 'center' );
} }
else {
dom.wrapper.classList.remove( 'center' );
}
if( config.mouseWheel ) { if( config.mouseWheel ) {
document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF document.addEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
document.addEventListener( 'mousewheel', onDocumentMouseScroll, false ); document.addEventListener( 'mousewheel', onDocumentMouseScroll, false );
} }
else {
document.removeEventListener( 'DOMMouseScroll', onDocumentMouseScroll, false ); // FF
document.removeEventListener( 'mousewheel', onDocumentMouseScroll, false );
}
// 3D links // 3D links
if( config.rollingLinks ) { if( config.rollingLinks ) {
linkify(); enable3DLinks();
}
else {
disable3DLinks();
} }
// Load the theme in the config, if it's not already loaded // Load the theme in the config, if it's not already loaded
@ -383,6 +393,9 @@ var Reveal = (function(){
} }
} }
// Force a layout to make sure the current config is accounted for
layout();
} }
/** /**
@ -390,6 +403,8 @@ var Reveal = (function(){
*/ */
function addEventListeners() { function addEventListeners() {
eventsAreBound = true;
window.addEventListener( 'hashchange', onWindowHashChange, false ); window.addEventListener( 'hashchange', onWindowHashChange, false );
window.addEventListener( 'resize', onWindowResize, false ); window.addEventListener( 'resize', onWindowResize, false );
@ -424,6 +439,8 @@ var Reveal = (function(){
*/ */
function removeEventListeners() { function removeEventListeners() {
eventsAreBound = false;
document.removeEventListener( 'keydown', onDocumentKeyDown, false ); document.removeEventListener( 'keydown', onDocumentKeyDown, false );
window.removeEventListener( 'hashchange', onWindowHashChange, false ); window.removeEventListener( 'hashchange', onWindowHashChange, false );
window.removeEventListener( 'resize', onWindowResize, false ); window.removeEventListener( 'resize', onWindowResize, false );
@ -524,28 +541,79 @@ var Reveal = (function(){
/** /**
* Wrap all links in 3D goodness. * Wrap all links in 3D goodness.
*/ */
function linkify() { function enable3DLinks() {
if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) { if( supports3DTransforms && !( 'msPerspective' in document.body.style ) ) {
var nodes = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' ); var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a:not(.image)' );
for( var i = 0, len = nodes.length; i < len; i++ ) { for( var i = 0, len = anchors.length; i < len; i++ ) {
var node = nodes[i]; var anchor = anchors[i];
if( node.textContent && !node.querySelector( '*' ) && ( !node.className || !node.classList.contains( node, 'roll' ) ) ) { if( anchor.textContent && !anchor.querySelector( '*' ) && ( !anchor.className || !anchor.classList.contains( anchor, 'roll' ) ) ) {
var span = document.createElement('span'); var span = document.createElement('span');
span.setAttribute('data-title', node.text); span.setAttribute('data-title', anchor.text);
span.innerHTML = node.innerHTML; span.innerHTML = anchor.innerHTML;
node.classList.add( 'roll' ); anchor.classList.add( 'roll' );
node.innerHTML = ''; anchor.innerHTML = '';
node.appendChild(span); anchor.appendChild(span);
} }
} }
} }
} }
/**
* Unwrap all 3D links.
*/
function disable3DLinks() {
var anchors = document.querySelectorAll( SLIDES_SELECTOR + ' a.roll' );
for( var i = 0, len = anchors.length; i < len; i++ ) {
var anchor = anchors[i];
var span = anchor.querySelector( 'span' );
if( span ) {
anchor.classList.remove( 'roll' );
anchor.innerHTML = span.innerHTML;
}
}
}
/**
* Return a sorted fragments list, ordered by an increasing
* "data-fragment-index" attribute.
*
* Fragments will be revealed in the order that they are returned by
* this function, so you can use the index attributes to control the
* order of fragment appearance.
*
* To maintain a sensible default fragment order, fragments are presumed
* to be passed in document order. This function adds a "fragment-index"
* attribute to each node if such an attribute is not already present,
* and sets that attribute to an integer value which is the position of
* the fragment within the fragments list.
*/
function sortFragments( fragments ) {
var a = toArray( fragments );
a.forEach( function( el, idx ) {
if( !el.hasAttribute( 'data-fragment-index' ) ) {
el.setAttribute( 'data-fragment-index', idx );
}
} );
a.sort( function( l, r ) {
return l.getAttribute( 'data-fragment-index' ) - r.getAttribute( 'data-fragment-index');
} );
return a
}
/** /**
* Applies JavaScript-controlled layout rules to the * Applies JavaScript-controlled layout rules to the
* presentation. * presentation.
@ -602,31 +670,30 @@ var Reveal = (function(){
dom.slides.style.transform = transform; dom.slides.style.transform = transform;
} }
if( config.center ) { // Select all slides, vertical and horizontal
var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) );
// Select all slides, vertical and horizontal for( var i = 0, len = slides.length; i < len; i++ ) {
var slides = toArray( document.querySelectorAll( SLIDES_SELECTOR ) ); var slide = slides[ i ];
// Determine the minimum top offset for slides // Don't bother updating invisible slides
var minTop = -slideHeight / 2; if( slide.style.display === 'none' ) {
continue;
for( var i = 0, len = slides.length; i < len; i++ ) { }
var slide = slides[ i ];
// Don't bother updating invisible slides
if( slide.style.display === 'none' ) {
continue;
}
if( config.center ) {
// Vertical stacks are not centered since their section // Vertical stacks are not centered since their section
// children will be // children will be
if( slide.classList.contains( 'stack' ) ) { if( slide.classList.contains( 'stack' ) ) {
slide.style.top = 0; slide.style.top = 0;
} }
else { else {
slide.style.top = Math.max( - ( slide.offsetHeight / 2 ) - 20, minTop ) + 'px'; slide.style.top = Math.max( - ( slide.offsetHeight / 2 ) - 20, -slideHeight / 2 ) + 'px';
} }
} }
else {
slide.style.top = '';
}
} }
@ -871,9 +938,15 @@ var Reveal = (function(){
*/ */
function pause() { function pause() {
var wasPaused = dom.wrapper.classList.contains( 'paused' );
cancelAutoSlide(); cancelAutoSlide();
dom.wrapper.classList.add( 'paused' ); dom.wrapper.classList.add( 'paused' );
if( wasPaused === false ) {
dispatchEvent( 'paused' );
}
} }
/** /**
@ -881,9 +954,15 @@ var Reveal = (function(){
*/ */
function resume() { function resume() {
var wasPaused = dom.wrapper.classList.contains( 'paused' );
cueAutoSlide(); cueAutoSlide();
dom.wrapper.classList.remove( 'paused' ); dom.wrapper.classList.remove( 'paused' );
if( wasPaused ) {
dispatchEvent( 'resumed' );
}
} }
/** /**
@ -996,7 +1075,7 @@ var Reveal = (function(){
// Show fragment, if specified // Show fragment, if specified
if( typeof f !== 'undefined' ) { if( typeof f !== 'undefined' ) {
var fragments = currentSlide.querySelectorAll( '.fragment' ); var fragments = sortFragments( currentSlide.querySelectorAll( '.fragment' ) );
toArray( fragments ).forEach( function( fragment, indexf ) { toArray( fragments ).forEach( function( fragment, indexf ) {
if( indexf < f ) { if( indexf < f ) {
@ -1367,7 +1446,8 @@ var Reveal = (function(){
// Vertical slides: // Vertical slides:
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) { if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ); var verticalFragments = sortFragments( document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ) );
if( verticalFragments.length ) { if( verticalFragments.length ) {
verticalFragments[0].classList.add( 'visible' ); verticalFragments[0].classList.add( 'visible' );
@ -1378,7 +1458,8 @@ var Reveal = (function(){
} }
// Horizontal slides: // Horizontal slides:
else { else {
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ); var horizontalFragments = sortFragments( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment:not(.visible)' ) );
if( horizontalFragments.length ) { if( horizontalFragments.length ) {
horizontalFragments[0].classList.add( 'visible' ); horizontalFragments[0].classList.add( 'visible' );
@ -1402,7 +1483,8 @@ var Reveal = (function(){
// Vertical slides: // Vertical slides:
if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) { if( document.querySelector( VERTICAL_SLIDES_SELECTOR + '.present' ) ) {
var verticalFragments = document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' ); var verticalFragments = sortFragments( document.querySelectorAll( VERTICAL_SLIDES_SELECTOR + '.present .fragment.visible' ) );
if( verticalFragments.length ) { if( verticalFragments.length ) {
verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' ); verticalFragments[ verticalFragments.length - 1 ].classList.remove( 'visible' );
@ -1413,7 +1495,8 @@ var Reveal = (function(){
} }
// Horizontal slides: // Horizontal slides:
else { else {
var horizontalFragments = document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' ); var horizontalFragments = sortFragments( document.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR + '.present .fragment.visible' ) );
if( horizontalFragments.length ) { if( horizontalFragments.length ) {
horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' ); horizontalFragments[ horizontalFragments.length - 1 ].classList.remove( 'visible' );
@ -1783,22 +1866,26 @@ var Reveal = (function(){
// TODO There's a bug here where the event listeners are not // TODO There's a bug here where the event listeners are not
// removed after deactivating the overview. // removed after deactivating the overview.
if( isOverview() ) { if( eventsAreBound && isOverview() ) {
event.preventDefault(); event.preventDefault();
deactivateOverview();
var element = event.target; var element = event.target;
while( element && !element.nodeName.match( /section/gi ) ) { while( element && !element.nodeName.match( /section/gi ) ) {
element = element.parentNode; element = element.parentNode;
} }
if( element.nodeName.match( /section/gi ) ) { if( element && !element.classList.contains( 'disabled' ) ) {
var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
v = parseInt( element.getAttribute( 'data-index-v' ), 10 ); deactivateOverview();
if( element.nodeName.match( /section/gi ) ) {
var h = parseInt( element.getAttribute( 'data-index-h' ), 10 ),
v = parseInt( element.getAttribute( 'data-index-v' ), 10 );
slide( h, v );
}
slide( h, v );
} }
} }
@ -1812,6 +1899,7 @@ var Reveal = (function(){
return { return {
initialize: initialize, initialize: initialize,
configure: configure,
// Navigation methods // Navigation methods
slide: slide, slide: slide,

4
js/reveal.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,31 +1,34 @@
{ {
"name": "reveal.js", "name": "reveal.js",
"version": "2.3.0", "version": "2.3.0",
"description": "The HTML Presentation Framework", "description": "The HTML Presentation Framework",
"homepage": "http://lab.hakim.se/reveal-js", "homepage": "http://lab.hakim.se/reveal-js",
"author": { "author": {
"name": "Hakim El Hattab", "name": "Hakim El Hattab",
"email": "hakim.elhattab@gmail.com", "email": "hakim.elhattab@gmail.com",
"web": "http://hakim.se" "web": "http://hakim.se"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/hakimel/reveal.js.git" "url": "git://github.com/hakimel/reveal.js.git"
}, },
"engines": { "engines": {
"node": "~0.8.0" "node": "~0.8.0"
}, },
"scripts": { "scripts": {
"test": "grunt lint qunit" "test": "grunt jshint"
}, },
"dependencies": { "dependencies": {
"underscore" : "~1.3.3", "underscore": "~1.3.3",
"express" : "~2.5.9", "express": "~2.5.9",
"socket.io" : "~0.9.6", "socket.io": "~0.9.6",
"mustache" : "~0.4.0" "mustache": "~0.4.0"
}, },
"devDependencies": { "devDependencies": {
"grunt-contrib-mincss": "~0.3.1", "grunt-contrib-jshint": "~0.2.0",
"grunt": "~0.3.17" "grunt-contrib-cssmin": "~0.4.1",
} "grunt-contrib-uglify": "~0.1.1",
"grunt-contrib-watch": "~0.2.0",
"grunt": "~0.4.0"
}
} }

View File

@ -0,0 +1,97 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js - Markdown Demo</title>
<link rel="stylesheet" href="../../css/reveal.css">
<link rel="stylesheet" href="../../css/theme/default.css" id="theme">
</head>
<body>
<div class="reveal">
<div class="slides">
<!-- Use external markdown resource, and separate slides by three newlines; vertical slides by two newlines -->
<section data-markdown="example.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">
## Demo 1
Slide 1
---
## Demo 1
Slide 2
---
## Demo 1
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">
## Demo 2
Slide 1.1
--
## Demo 2
Slide 1.2
---
## Demo 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>
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme,
transition: Reveal.getQueryHash().transition || 'default',
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'showdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }
]
});
</script>
</body>
</html>

View File

@ -0,0 +1,29 @@
# Markdown Demo
## External 1.1
Content 1.1
## External 1.2
Content 1.2
## External 2
Content 2.1
## External 3.1
Content 3.1
## External 3.2
Content 3.2

View File

@ -6,16 +6,12 @@
throw 'The reveal.js Markdown plugin requires Showdown to be loaded'; throw 'The reveal.js Markdown plugin requires Showdown to be loaded';
} }
var sections = document.querySelectorAll( '[data-markdown]' ); var stripLeadingWhitespace = function(section) {
for( var i = 0, len = sections.length; i < len; i++ ) {
var section = sections[i];
var notes = section.querySelector( 'aside.notes' );
var template = section.querySelector( 'script' ); var template = section.querySelector( 'script' );
// strip leading whitespace so it isn't evaluated as code // strip leading whitespace so it isn't evaluated as code
var text = ( template || section ).innerHTML; var text = ( template || section ).textContent;
var leadingWs = text.match(/^\n?(\s*)/)[1].length, var leadingWs = text.match(/^\n?(\s*)/)[1].length,
leadingTabs = text.match(/^\n?(\t*)/)[1].length; leadingTabs = text.match(/^\n?(\t*)/)[1].length;
@ -27,11 +23,125 @@
text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' ); 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 ) { if( notes ) {
section.appendChild( notes ); section.appendChild( notes );
} }
}
};
querySlidingMarkdown();
queryMarkdownSlides();
})(); })();

View File

@ -225,6 +225,13 @@
}, 1000 ); }, 1000 );
// Navigate the main window when the notes slide changes
currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', function( event ) {
window.opener.Reveal.slide( event.indexh, event.indexv );
} );
} }
else { else {