merge support for notes when using external markdown

This commit is contained in:
Hakim El Hattab 2013-08-20 22:32:19 -04:00
commit 631a237b36
4 changed files with 54 additions and 24 deletions

View File

@ -55,7 +55,7 @@ This is based on [data-markdown](https://gist.github.com/1343518) from [Paul Iri
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. The ```data-charset``` attribute is optional and specifies which charset to use when loading the external file. 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. The ```data-charset``` attribute is optional and specifies which charset to use when loading the external file.
```html ```html
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n" data-charset="iso-8859-15"></section> <section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n" data-notes="^Note:" data-charset="iso-8859-15"></section>
``` ```
### Configuration ### Configuration
@ -478,7 +478,7 @@ If you want to add a theme of your own see the instructions here: [/css/theme/RE
reveal.js comes with a speaker notes plugin which can be used to present per-slide notes in a separate browser window. The notes window also gives you a preview of the next upcoming slide so it may be helpful even if you haven't written any notes. Press the 's' key on your keyboard to open the notes window. reveal.js comes with a speaker notes plugin which can be used to present per-slide notes in a separate browser window. The notes window also gives you a preview of the next upcoming slide so it may be helpful even if you haven't written any notes. Press the 's' key on your keyboard to open the notes window.
By default notes are written using standard HTML, see below, but you can add a ```data-markdown``` attribute to the ```<aside>``` to write them using Markdown. By default notes are written using standard HTML, see below, but you can add a ```data-markdown``` attribute to the ```<aside>``` to write them using Markdown, or separate your external markdown content file with the separator specified within your original declaration where notes begin.
```html ```html
<section> <section>
@ -490,6 +490,17 @@ By default notes are written using standard HTML, see below, but you can add a `
</section> </section>
``` ```
```html
<section data-markdown="example.md" data-separator="^\n\n\n" data-vertical="^\n\n" data-notes="^[[["></section>
# Title
## Sub-title
Here is some content...
[[[
These are my notes for this slide.
```
## Server Side Speaker Notes ## Server Side Speaker Notes
In some cases it can be desirable to run notes on a separate device from the one you're presenting on. The Node.js-based notes plugin lets you do this using the same note definitions as its client side counterpart. Include the required scripts by adding the following dependencies: In some cases it can be desirable to run notes on a separate device from the one you're presenting on. The Node.js-based notes plugin lets you do this using the same note definitions as its client side counterpart. Include the required scripts by adding the following dependencies:

View File

@ -87,7 +87,8 @@
dependencies: [ dependencies: [
{ src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } }, { src: '../../lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } }, { src: 'marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } } { src: 'markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '../notes/notes.js' }
] ]
}); });

View File

@ -6,6 +6,8 @@
Content 1.1 Content 1.1
Note: This will only appear in the speaker notes window.
## External 1.2 ## External 1.2

View File

@ -36,7 +36,9 @@
}; };
var twrap = function(el) { var twrap = function(el) {
return marked(el); var content = el.content || el;
content += el.asideContent ? ('<aside class="notes" data-markdown>' + el.asideContent + '</aside>') : '';
return '<script type="text/template">' + content + '</script>';
}; };
var getForwardedAttributes = function(section) { var getForwardedAttributes = function(section) {
@ -48,7 +50,7 @@
value = attributes[i].value; value = attributes[i].value;
// disregard attributes that are used for markdown loading/parsing // disregard attributes that are used for markdown loading/parsing
if( /data\-(markdown|separator|vertical)/gi.test( name ) ) continue; if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
if( value ) { if( value ) {
result.push( name + '=' + value ); result.push( name + '=' + value );
@ -61,45 +63,61 @@
return result.join( ' ' ); return result.join( ' ' );
}; };
var slidifyMarkdown = function(markdown, separator, vertical, attributes) { var slidifyMarkdown = function(markdown, separator, vertical, notes, attributes) {
separator = separator || '^\n---\n$'; separator = separator || '^\n---\n$';
notes = notes || 'note:';
var reSeparator = new RegExp(separator + (vertical ? '|' + vertical : ''), 'mg'), var separatorRegex = new RegExp( separator + ( vertical ? '|' + vertical : '' ), 'mg' ),
reHorSeparator = new RegExp(separator), horizontalSeparatorRegex = new RegExp( separator ),
notesSeparatorRegex = new RegExp( notes, 'mgi' ),
matches, matches,
noteMatch,
lastIndex = 0, lastIndex = 0,
isHorizontal, isHorizontal,
wasHorizontal = true, wasHorizontal = true,
content, content,
asideContent,
slide,
sectionStack = [], sectionStack = [],
markdownSections = ''; markdownSections = '';
// iterate until all blocks between separators are stacked up // iterate until all blocks between separators are stacked up
while( matches = reSeparator.exec(markdown) ) { while( matches = separatorRegex.exec( markdown ) ) {
asideContent = null;
// determine direction (horizontal by default) // determine direction (horizontal by default)
isHorizontal = reHorSeparator.test(matches[0]); isHorizontal = horizontalSeparatorRegex.test( matches[0] );
if( !isHorizontal && wasHorizontal ) { if( !isHorizontal && wasHorizontal ) {
// create vertical stack // create vertical stack
sectionStack.push([]); sectionStack.push( [] );
} }
// pluck slide content from markdown input // pluck slide content from markdown input
content = markdown.substring(lastIndex, matches.index); content = markdown.substring( lastIndex, matches.index );
noteMatch = content.split( notesSeparatorRegex );
if( noteMatch.length === 2 ) {
content = noteMatch[0];
asideContent = noteMatch[1].trim();
}
slide = {
content: content,
asideContent: asideContent || ""
};
if( isHorizontal && wasHorizontal ) { if( isHorizontal && wasHorizontal ) {
// add to horizontal stack // add to horizontal stack
sectionStack.push(content); sectionStack.push(slide);
} else { } else {
// add to vertical stack // add to vertical stack
sectionStack[sectionStack.length-1].push(content); sectionStack[sectionStack.length-1].push(slide);
} }
lastIndex = reSeparator.lastIndex; lastIndex = separatorRegex.lastIndex;
wasHorizontal = isHorizontal; wasHorizontal = isHorizontal;
} }
// add the remaining slide // add the remaining slide
@ -107,15 +125,13 @@
// flatten the hierarchical stack, and insert <section data-markdown> tags // flatten the hierarchical stack, and insert <section data-markdown> tags
for( var k = 0, klen = sectionStack.length; k < klen; k++ ) { for( var k = 0, klen = sectionStack.length; k < klen; k++ ) {
// horizontal
if( typeof sectionStack[k] === 'string' ) {
markdownSections += '<section '+ attributes +'>' + twrap( sectionStack[k] ) + '</section>';
}
// vertical // vertical
else { if( sectionStack[k].propertyIsEnumerable(length) && typeof sectionStack[k].splice === 'function' ) {
markdownSections += '<section '+ attributes +'>' + markdownSections += '<section '+ attributes +'>' +
'<section>' + sectionStack[k].map(twrap).join('</section><section>') + '</section>' + '<section data-markdown>' + sectionStack[k].map(twrap).join('</section><section data-markdown>') + '</section>' +
'</section>'; '</section>';
} else {
markdownSections += '<section '+ attributes +' data-markdown>' + twrap( sectionStack[k] ) + '</section>';
} }
} }
@ -145,7 +161,7 @@
xhr.onreadystatechange = function () { xhr.onreadystatechange = function () {
if( xhr.readyState === 4 ) { if( xhr.readyState === 4 ) {
if (xhr.status >= 200 && xhr.status < 300) { if (xhr.status >= 200 && xhr.status < 300) {
section.outerHTML = slidifyMarkdown( xhr.responseText, section.getAttribute('data-separator'), section.getAttribute('data-vertical'), getForwardedAttributes(section) ); section.outerHTML = slidifyMarkdown( xhr.responseText, section.getAttribute('data-separator'), section.getAttribute('data-vertical'), section.getAttribute('data-notes'), getForwardedAttributes(section) );
} else { } else {
section.outerHTML = '<section data-state="alert">ERROR: The attempt to fetch ' + url + ' failed with the HTTP status ' + xhr.status + section.outerHTML = '<section data-state="alert">ERROR: The attempt to fetch ' + url + ' failed with the HTTP status ' + xhr.status +
'. Check your browser\'s JavaScript console for more details.' + '. Check your browser\'s JavaScript console for more details.' +
@ -164,7 +180,7 @@
} else if( section.getAttribute('data-separator') ) { } else if( section.getAttribute('data-separator') ) {
var markdown = stripLeadingWhitespace(section); var markdown = stripLeadingWhitespace(section);
section.outerHTML = slidifyMarkdown( markdown, section.getAttribute('data-separator'), section.getAttribute('data-vertical'), getForwardedAttributes(section) ); section.outerHTML = slidifyMarkdown( markdown, section.getAttribute('data-separator'), section.getAttribute('data-vertical'), section.getAttribute('data-notes'), getForwardedAttributes(section) );
} }
} }